1. 程式人生 > >JVM之JMM詳解(卷一)

JVM之JMM詳解(卷一)

1 序言:

   在講解Java的記憶體模型之前,我們可以看看物理機在遇到併發問題時所想出的處理方案(物理機和Java虛擬機器在解決併發問題有不少相似的地方,具有很大的參考價值)。本章旨在剖析Java的記憶體模型以及讓讀者明白Java併發程式設計裡不知其所以然的地方。(推薦書籍《Java併發程式設計藝術》《深入理解Java虛擬機器 第二版》) 

2 物理機併發解決方案

  2.1 處理器,快取記憶體,主記憶體間的互動圖

image
講解:“讓計算機併發執行若干個運算任務”與“更充分地利用計算機處理器的效能”之間因果關係,看起來順理成章,實際上他們之間的關心並沒有想象中的那麼簡單。由於計算機絕大多數的運算任務肯定不能交給處理器來負責,至少要跟記憶體打交道。所以I/0流就是計算機其中一種限制,所以為了防止消耗過多的時間在資料讀取方面,所以如圖”快取記憶體“cache就出現了,計算機將要處理的資料先從主記憶體讀到快取區中。在這個過程中我們不難發現每個處理器都有自己的快取記憶體區,那麼從主記憶體讀來的資料如何保證正確性了。這時快取一致性協議就出現了。
   資料問題解決了那如何提高物理機的效能?聰明的人總有辦法,那就是讓處理器內部的運算單元能儘量被充分利用。如何充分利用了? 那就是對輸入的程式碼進行亂序執行優化,處理器會在計算之後將亂序執行的結果重組,保證該結果與順序執行的結果是一致的,但不保證程式中各個語句計算的先後順序與輸入程式碼中的順序一致。(類似於Java記憶體模型的指令重排)。 

3Java的記憶體模型

目的:遮蔽掉各種硬體和作業系統的記憶體訪問差異,以實現讓Java程式在各種平臺下都能達到一致的記憶體訪問效果。即一次編譯到處執行。

3.1 工作記憶體和主記憶體

如圖 image

記憶體的互動操作

Lock(鎖定): 作用與主記憶體的變數,它把一個變數標識為一條執行緒獨佔的狀態.
unlock(解鎖): 作用於主記憶體的變數,它把一個處於解鎖狀態的變數釋放出來,釋放後的變數才可以別其他執行緒鎖定。
read(讀取): 作用於主記憶體變數,把一個變數值從主記憶體傳輸到執行緒的工作記憶體中,以便隨後的load動作使用
load(載入): 作用於工作記憶體的變數,它把read操作從主記憶體中得到的變數值放入工作記憶體的變數副本中。
use(使用): 作用於工作記憶體的變數,把工作記憶體中的一個變數值傳遞給執行引擎,每當虛擬機器遇到一個需要使用變數的值的位元組碼指令時將會執行這個操作。
assign(賦值): 作用於工作記憶體的變數,它把一個從執行引擎接收到的值賦值給工作記憶體的變數,每當虛擬機器遇到一個給變數賦值的位元組碼指令時執行這個操作。
store(儲存): 作用於工作記憶體的變數,把工作記憶體中的一個變數的值傳送到主記憶體中,以便隨後的write的操作。
write(寫入): 作用於主記憶體的變數,它把store操作從工作記憶體中一個變數的值傳送到主記憶體的變數中。

從上圖可知執行緒之間的通訊是如何進行的?

如圖 image
從圖中可以看出執行緒A和執行緒B的通訊實質就是執行緒A把它本地記憶體的值寫到主記憶體中,執行緒B去值不是從本地記憶體中取而是從主記憶體中去取得值,這樣間接的實現了執行緒A與執行緒B之間的通訊。

從上述的通訊圖,我們不難象到Java多執行緒的一個非常重要的關鍵字volatile,下面我們就一起看看volatile的工作原理吧!(卷二)