標籤:
Java虛擬機器規範中試圖定義一種java記憶體模型(java Memory Model,jmm)來屏蔽掉各種硬體和作業系統的記憶體訪問差異,以實現讓java程式在各種平台下都能達到一致的記憶體訪問效果。
Java記憶體模型的主要目標是定義程式中各個變數的訪問規則,即在虛擬機器中將變數儲存到記憶體和從記憶體中取出變數這樣的底層細節。
Java記憶體模型規定了所有的變數都儲存在主記憶體中。每條線程還有自己的工作記憶體,線程的工作記憶體中儲存了被該線程使用到的變數的主記憶體副本拷貝。
關於主記憶體與工作記憶體之間具體的互動協議,java記憶體模型中定義了以下8種操作來完成,虛擬機器實現時必須保證下面提及的每一種操作都是原子的、不可再分的。
1、Lock(鎖定):作用於主記憶體的變數,它把一個變數標識為一條線程獨佔的狀態。
2、unlock(解鎖):作用於主記憶體的變數,它把一個處於鎖定狀態的變數釋放出來,釋放後的變數才可以被其它線程鎖定
3、read(讀取):作用於主記憶體的變數,它把一個變數的值從主記憶體傳輸到線程的工作記憶體變數副本中
4、load(載入):作用於工作記憶體的變數,它把read操作從主記憶體中得到的變數值放入工作記憶體的變數副本中
5、use(使用):作用於工作記憶體的變數,它把工作記憶體中的一個變數值傳遞給執行引擎,每當虛擬機器遇到一個需要使用到變數的值的位元組碼指令時將會執行這個操作
6、assign(賦值):作用於工作記憶體的變數,它把一個從執行引擎接收到的值賦給工作記憶體的變數,每當虛擬機器遇到一個給變數賦值的位元組碼指令時執行這個操作
7、store(儲存):作用於工作記憶體的變數,它把工作記憶體中一個變數的值傳送到主記憶體中以便隨後的write操作使用
8、write(寫入):作用於主記憶體的變數,它把store操作從工作記憶體中得到的變數的值放入主記憶體的變數中
如果要把一個變數從主記憶體複製到工作記憶體,那就要順序地執行read和load操作,如果把變數從工作記憶體同步回主記憶體,就要順序地執行store和write操作。Java記憶體模型只要求上述兩個操作必須按順序執行,而沒有保證連續執行。
8.1對於volatile型變數的特殊規則
當一個變數定義為volatile之後,它將具備兩種特性,第一是保證此變數對所有線程的可見度,這裡的可見度是指當一條線程修改了這個變數的值,新值對於其他線程來說是可以立即得知的。而普通變數不能做到這一點,普通變數的值線上程間傳遞均需要通過主記憶體來完成。
由於volatile變數只能保證可見度,在不符合以下兩條規則的運算情境中,我們仍然要通過加鎖來保證原子性。
1、運算結果並不依賴變數的當前值,或者能夠確保只有單一的線程修改變數的值
2、變數不需要與其他的狀態變數共同參與不變約束
使用volatile變數的第二個語義是禁止指令重排序最佳化,普通的變數僅僅會保證在該方法的執行過程中所有依賴賦值結果的地方都能獲得正確的結果,而不能保證變數的賦值操作的順序與程式碼中的執行順序一致。
java記憶體模型