1. 程式人生 > 實用技巧 >對於Java volatile的理解

對於Java volatile的理解

對於Java volatile的理解

一、什麼是volatile

簡單來說就是Java併發機制的一個關鍵字,可以協助我們進行併發程式設計,同時也是面試高頻考點。作用於欄位(屬性),可以保證改變數的記憶體可見性。

二、什麼是記憶體可見性

1.理解記憶體可見性的前提是理解JMM(Java的記憶體模型),如下圖。
我們知道執行緒在JMM的管理下有自己獨立的記憶體空間,叫做 工作記憶體 ,執行緒的工作記憶體相互隔離不會共享但可以通訊,與之相反的是主記憶體,對各個執行緒資料共享。

在這裡我們可以思考一個問題,這兩種記憶體有什麼區別?
回憶Java記憶體模型,我們可以知道Java記憶體包括了Stack和Head。其實工作記憶體就是Stack,主記憶體是Head。
Java記憶體模型

2.執行緒的工作過程是怎樣的?
①執行緒從主記憶體copy一份資料到工作記憶體;
②然後線上程內部處理完後;
③資料寫在工作記憶體中;
④把工作記憶體中的資料更新到主記憶體中。

三、舉個例子

x = x+1

1.把x=1copy到執行緒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包下的原子類。