對於Java volatile的理解
對於Java volatile的理解
一、什麼是volatile
簡單來說就是Java併發機制的一個關鍵字,可以協助我們進行併發程式設計,同時也是面試高頻考點。作用於欄位(屬性),可以保證改變數的記憶體可見性。
二、什麼是記憶體可見性
1.理解記憶體可見性的前提是理解JMM(Java的記憶體模型),如下圖。
我們知道執行緒在JMM的管理下有自己獨立的記憶體空間,叫做 工作記憶體 ,執行緒的工作記憶體相互隔離不會共享但可以通訊,與之相反的是主記憶體,對各個執行緒資料共享。
回憶Java記憶體模型,我們可以知道Java記憶體包括了Stack和Head。其實工作記憶體就是Stack,主記憶體是Head。
2.執行緒的工作過程是怎樣的?
①執行緒從主記憶體copy一份資料到工作記憶體;
②然後線上程內部處理完後;
③資料寫在工作記憶體中;
④把工作記憶體中的資料更新到主記憶體中。
三、舉個例子
x = x+1
1.把x=1
copy到執行緒A的工作記憶體;
2.線上程A的工作記憶體處理運算;
3.資料處理完畢,執行緒A的工作記憶體中記錄著x=2
,但此時在主記憶體中仍為x=1
;
4.最後把執行緒A的工作記憶體記錄的x=2
x=2
;
四、補充一個知識點
Java對於賦值字面量的操作是原子性的,比如說:
int a = 100;
,可以直接把100一次性賦值給a。
但是,int b = a;
並不是原子型的操作,因為這裡面需要兩個步驟,首先讀取a的值,然後才把a的值賦給b。
五、問題的提出
從上面的例子,我們大概就知道了,在多執行緒的環境中,資料的操作如果沒有某種保護措施,就有可能產生併發問題。
舉個例子,同樣是:
x = x+1
現在有A、B兩個執行緒執行該程式碼,當A執行緒把x的值copy到工作記憶體,並且完成計算,但是沒有把資料更新到主記憶體,此時在主記憶體中x=1
,執行緒B開始工作,把x的值copy到B的工作記憶體…問題很顯然了,此時執行緒B copy的值為x=1
x=2
,而正確答案應該是x=3
。
六、迴歸什麼是記憶體的可見性
有了以上知識的疏通,大概就能夠理解什麼是記憶體的可見性了,記憶體的可見性指的是 每次讀取到的變數,一定是最新的資料 ,怎樣來理解呢?
①執行緒處理完的資料及時更新到主存中;
②被其他執行緒處理著的資料禁止被讀取;
而volatile正是Java提供的可以達到保持可見性的目的的關鍵字!
七、應用
可以檢視java.util.concurrent包下的原子類。