一、volatile決議
1.計算機內部的記憶體模型
- 我們知道計算機內部含有記憶體和CPU,那么在進行計算的時候,記憶體讀寫還是太慢了,因此在記憶體和CPU之間還是有一個快取cache
- 那么我們知道如果是一個共享變數的話,就會導致,記憶體中變數和快取中的變數由于多執行緒同步不及時,也就是說,一個執行緒中的快取還沒來的急寫入記憶體,此時有可能在記憶體中的變數被其他執行緒讀取了,
- 解決這個問題可以:1)通過在總線加LOCK#鎖的方式;2)通過快取一致性協議
- 第一種方式效率低下,很難實作多執行緒;第二種方式有一個著名MSI協議,就是指當快取寫入記憶體之后,會向其他執行緒發出信號,共享變數數值已變,如果需要的話,需要重新更新,

2.并發編程的三個概念
- 原子性:一組操作要么全部執行成功,要么全部執行失敗,不存在部分成功,部分失敗的情況
- 可見性:一個執行緒對共享變數在快取中已經更改,但是還沒有來得及寫入記憶體,此時又有一個執行緒訪問了該變數,那么就會出現資料不一致
- 有序性:各個陳述句的執行其實不一定按照從上到下的順序,但是最后個結果一定和按從上到下執行的結果一致,因為如果陳述句不相干,先執行哪個后執行哪個無所謂,但是陳述句相干,就會按照從上到下的正常順序,
3.Java中的記憶體模型
- 與計算機的記憶體模型相似,也會有三大特性
- 原子性,這個特性,可以通過synchronnized和lock來保證
- 可見性,Java通過violate來保證,如果共享變數是有violate來修飾那么就是保證,如果改變了它的值就能保證絕對會寫入記憶體之后,別的執行緒才會呼叫,
- 有序性,Java中存在happens-before原則來保證有序性,如果兩條陳述句通過該原則仍然不能推斷先后執行的先后順序,那么這兩個陳述句是不是有序的,誰先執行都說不準,
- 程式次序規則:一個執行緒內,按照代碼順序,書寫在前面的操作先行發生于書寫在后面的操作
- (1)程式次序規則:一個執行緒內,按照代碼順序,書寫在前面的操作先行發生于書寫在后面的操作
- (2)鎖定規則:一個unLock操作先行發生于后面對同一個鎖額lock操作
- (3)volatile變數規則:對一個變數的寫操作先行發生于后面對這個變數的讀操作
- (4)傳遞規則:如果操作A先行發生于操作B,而操作B又先行發生于操作C,則可以得出操作A先行發生于操作C
- (5)執行緒啟動規則:Thread物件的start()方法先行發生于此執行緒的每個一個動作
- (6)執行緒中斷規則:對執行緒interrupt()方法的呼叫先行發生于被中斷執行緒的代碼檢測到中斷事件的發生
- (7)執行緒終結規則:執行緒中所有的操作都先行發生于執行緒的終止檢測,我們可以通過Thread.join()方法結束、Thread.isAlive()的回傳值手段檢測到執行緒已經終止執行
- (8)物件終結規則:一個物件的初始化完成先行發生于他的finalize()方法的開始
4.下面我們舉個例子
package com.ruigege.threadFoundation1;
public class TestViolate {
public volatile int inc =1;
public static void main(String[] args) {
TestViolate test = new TestViolate();
for(int i=0;i<10;i++) {
//創建十個執行緒,對inc進行自增操作
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for(int j=0;j<10000;j++) {
test.inc++;
}
}
});
thread.start();
}
while(Thread.activeCount()>1) {
Thread.yield();//如果存在還沒有結束的執行緒,就需要盡量讓出CPU供它們運行
}
System.out.println(test.inc);
}
}
- 我們將這段代碼運行三次



- 這結果和我們預想的不一樣,為什么呢?下次再說
二、原始碼:
- 所在包:com.ruigege.ThreadFoundation1
https://github.com/ruigege66/ConcurrentJava- CSDN:https://blog.csdn.net/weixin_44630050
- 博客園:https://www.cnblogs.com/ruigege0000/
- 歡迎關注微信公眾號:傅里葉變換,個人賬號,僅用于技術交流

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/201723.html
標籤:Java
上一篇:Maven
下一篇:Docker安裝及鏡像加速器配置
