1. 程式人生 > 實用技巧 >volatile關鍵字——深刻理解

volatile關鍵字——深刻理解

1.Java記憶體模型及volatile基本概念

1.1 計算機記憶體概要

volatile修飾符其實不是Java語言首創,早在C和C++傍邊就已經存在。在講解Java的volatile關鍵字之前,有需要先了解一下Java的記憶體模型。

背景:計算機執行程式的時候每條指令都是在cpu中執行的,那麼執行指令的同時勢必會有讀取和寫入的操作,那麼這樣就引申出了一個問題。那麼在程式執行時資料的儲存是在計算機中的主存中(實體記憶體)的而記憶體的讀取和寫入的速度與cpu的執行指令速度相比差距是很大的,這樣就造成了與記憶體互動時程式執行效率大大降低,因此在cpu中就有了快取記憶體。

也就說計算機cpu在執行指令時將主存中的資料複製到快取記憶體中,將結果運算完畢後在將運算結果重新整理到主存中

。廢話不多說看圖說話:

計算機cpu會將運算資料複製到快取記憶體中。但是這樣如果在單執行緒是沒有問題的(單核多執行緒也是有問題的)。舉例說明:

i=i+1;

假設i變數初始值為0,這段程式碼理想結果是2,單CPU並不一定這樣來計算,假如有AB兩個執行緒,同時讀取了這段程式碼,同時將變數複製到了快取記憶體,A執行緒將資料執行完畢後將變數重新整理到主存中i=1,而B執行緒也同時執行完畢將變數也重新整理到主存中i=1,但是AB變數在運算時讀取的都是快取記憶體的,AB執行緒的快取記憶體是互相不知道其中的值的,那麼這樣就引申出了快取一致性問題

為了解決快取一致性問題,有兩個辦法:

  1. 通過匯流排加LOCK鎖的方式
  2. 通過快取一致協議
早期的cpu中是通過在匯流排加鎖來解決快取不一致的,因為計算機cpu通訊是通過匯流排來執行的,如果在總線上面加鎖的話就阻塞來其他cpu對該變數的訪問,如上面的程式碼在程式執行時匯流排發出lock指令,那麼只有在這段程式碼執行完畢後其他cpu才能讀取變數執行相應的指令,這樣就解決了快取一致性問題。

但是上面的方式會有一個問題,由於在鎖住匯流排期間,其他CPU無法訪問記憶體,導致效率低下。

1.2 Java記憶體模型

Java記憶體模型簡稱JMM(Java Memory Model),是Java虛擬機器所界說的一種抽象規範,用來遮蔽不合硬體和作業系統的記憶體拜候差別,讓java程式在各種平臺下都能達到一致的記憶體拜候效果。

兩個概念:

  1. 主記憶體(Main Memory)
    可以簡單理解為計算機傍邊的記憶體,但又不完全同等。主記憶體被所有的執行緒所共享,對一個共享變數(好比靜態變數,或是堆記憶體中的例項)來說,主記憶體傍邊儲存了它的“本尊”。
  2. 工作記憶體(Working Memory)

2.volatile實現原理

3.volatile適用場景

4.volatile記憶體語義及實現(記憶體屏障)