今年9月份要找工作,無意間看到一篇部落格,就想著把裡面的知識點總結一下,鞏固一下基礎知識,為找工作做一些準備:
http://blog.csdn.net/pistolove/article/details/46753275 Java記憶體模型 記憶體間互動操作 Java記憶體模型的概述
記憶體模型概念:屏蔽掉各種硬體和作業系統的記憶體訪問差異,以實現讓Java程式在各種平台下都能達到一致的記憶體訪問效果。
Java記憶體模型目標: 定義程式中各變數的訪問規則,即在虛擬機器中將變數儲存到記憶體和從記憶體中取出變數這樣的底層細節。 Java記憶體模型的規定
所有的變數都儲存在主記憶體中。 每條線程都有自己的工作記憶體。 不同的線程之間無法直接存取對方工作記憶體中的變數,線程間變數值的傳遞均需要通過主記憶體才能完成。 注意事項
上述的變數包括執行個體欄位、靜態欄位和構成數組對象的元素,但不包括局部變數和方法參數(以為它們是線程私人的,不共用)。 線程的工作記憶體中儲存了被改線程使用到的變數的主記憶體的副本拷貝,線程對所有操作都必須在工作記憶體中進行,而不能直接讀寫主存中的變數。 這裡講的主記憶體、工作記憶體與Java記憶體地區中的Java堆、棧、方法區並不是同一層次的記憶體劃分, 基本上沒有關係。 記憶體間互動操做
存在兩個問題:
1、一個變數如何從主記憶體拷貝到工作記憶體。
2、如何從工作記憶體同步回主記憶體。
對於這兩個問題,Java記憶體模型中定義了8種操作來完成,虛擬機器實現時必須保證下面提及的每一個操作都是原子的、不可再分的(double、long類型除外)。 8種操作
lock(鎖定):作用於主記憶體的變數,把一個變數標識為一條線程獨佔的狀態。 unclock(解鎖):作用於主記憶體的變數,把一個處於鎖定狀態的變數釋放出來,釋放後的變數才可以被其他線程鎖定。 read(讀取):作用於主記憶體的變數,把一個變數的值從主記憶體傳輸到線程的工作記憶體,以便隨後的load動作使用。 load(載入):作用於工作記憶體的變數,把read操作從主記憶體中得到的變數值放入工作記憶體的變數副本中。 use(使用):作用於工作記憶體的變數,把工作記憶體中一個變數的值傳遞給執行引擎。 assign(賦值):作用於工作記憶體的變數,把執行引擎接收到的值賦給工作記憶體的變數。 store(儲存):作用於工作記憶體的變數,把工作記憶體中一個變數的值傳送給主記憶體中,以便隨後的write操作使用。 write(寫入):作用於主記憶體的變數,把store操作從工作記憶體中得到的變數的值放入主記憶體的變數中。 操作的規定
不允許read和load、store和write操作之一單獨出現,即不允許一個變數從主記憶體中讀取了但工作記憶體不接受,或者工作記憶體發起了回寫但主記憶體不接受的情況出現。 不允許一個線程丟棄它的最近的assign操作,即變數在工作記憶體中改變了之後必須把該變化同步到主記憶體。 不允許一個線程無原因地(沒有發生任何assign操作)把資料從線程的工作記憶體同步到主記憶體。 一個新的變數只能在主記憶體中誕生,不允許在工作記憶體中直接使用一個未被初始化(load或assign)的變數,換句話說,就是對一個變數use、store操作之前,必須先執行過了assign和load操作。 一個變數在同一時刻只允許一個線程對其進行lock操作,但lock操作可以被同一條線程重複執行多次,多次執行lock後,只有執行相同次數的unclock操作,變數才會被解鎖。 如果對一個變數執行lock操作,那麼會清空工作記憶體次變數的值,在執行引擎使用這個變數前,需要重新執行load或assign操作初始設定變數的值。 如果對一個變數執行lock操作,那麼會清空工作記憶體次變數的值,在執行引擎使用這個變數前,需要重新執行load或assign操作初始設定變數的值。 對一個變數執行unclock之前,必須先把此變數同步回主記憶體中(執行store、write操作)。