1. 程式人生 > >併發程式設計與高併發解決方案學習(Java 記憶體模型)

併發程式設計與高併發解決方案學習(Java 記憶體模型)

JMM(Java Memory Model)

    JMM是一種規範,規範了Java虛擬機器與計算機記憶體是如何協同工作的,規定了一個執行緒如何和何時可以看到其他執行緒修改過的共享變數的值,以及在必須的時候如果同步的訪問共享變數。


棧    棧的優勢:存取速度比堆要快,僅次於計算機裡面的暫存器,棧的資料是可以共享的。缺點:存放資料的大小與生成器必須是確定的,棧中主要存放基本型別變數和物件的控制代碼。Java記憶體模型要求呼叫棧和本地變數存放線上程棧上,物件存放在堆上。

       Java中的堆是執行時資料區,堆是由垃圾回收負責的,堆可以動態的分配記憶體大小,聲稱期也不必告訴編譯器,因為它是在執行時動態分配記憶體, Java的垃圾收集器會自動的回收這些不在使用的資料,缺點:存取速度慢


                                                        硬體記憶體架構圖


 CPU在暫存器上執行操作的速度遠大於在主存中執行速度,這是因為CPU訪問暫存器的速度遠大於主存。

快取記憶體:由於計算機的儲存裝置與處理器的運算速度間有著幾個數量級的差異,所以現在計算機系統都不得不加入一層讀寫速度儘可能接近處理器速度的快取記憶體,來作為記憶體和處理器間的緩衝,將運算使用到的資料複製到快取中,讓運算能夠快速進行,當運算結束後再從快取同步回記憶體,這樣處理器就無需等待緩慢的記憶體讀寫了,CPU訪問快取層的速度快於訪問主存的速度,單通常比訪問內部暫存器的速度還要慢一點。每個cpu都有一個CPU快取層,一個CPU還有多層快取,在某一時刻,一個或多個快取行可能被讀的快取一個或多個快取行可能被重新整理給主存。

記憶體:一個計算機還包含一個主存,所有的CPU都可以訪問主存,主存通常比CPU的快取大的多。

                                                        Java記憶體模型


硬體記憶體架構沒有區分執行緒、棧、堆,對於硬體而言,所有的執行緒棧和堆都分佈在主記憶體裡面,部分執行緒棧和堆可能出現在CPU快取中和CPU內部的暫存器裡面。

                                                             Java記憶體模型抽象結構圖


Java記憶體模型-同步八種操作lock(鎖定):作用於主記憶體的變數,把一個變數標識為一條線城獨佔狀態unlock(解鎖):作用於主記憶體的變數,把一個處於鎖定狀態的變數釋放出來,釋放後的變數裁可以被其他執行緒鎖定read(讀取):作用於記憶體的變數,把一個變數值從主記憶體傳輸到執行緒的工作記憶體中,以便隨後的load動作使用。load(載入):作用於工作記憶體的變數,它把read操作從主記憶體中得到的變數值放入工作記憶體的變數副本中。use(使用):作用於工作記憶體的變數,把工作記憶體中的一個變數值傳遞給執行引擎assign(賦值):作用於工作記憶體的變數,它把一個從執行引擎接收到的值賦值給工作記憶體的變數store(儲存):作用於工作記憶體的變數,把工作記憶體中的一個變數的值傳送到主記憶體中,以便隨後的write的操作write(寫入):作用於主記憶體的變數,它把store操作從工作記憶體中一個變數的值傳送到主記憶體的變數中

Java記憶體模型-同步規則


※如果要把一個變數從主記憶體中複製到工作記憶體,就需要按順序地執行read和load操作,如果把變數從工作記憶體中同步回主記憶體中,就需要按順序執行store和write操作。但Java記憶體模型只要求上述操作必須按順序執行,而沒有保證必須要連續執行。

※不允許read和load、store和write操作之一單獨出現

※不允許一個執行緒丟棄它的最近assign的操作,即變數在工作記憶體中改變了之後必須同步到主記憶體中

※不允許一個執行緒無原因地(沒有發生過任何assign操作)從工作記憶體同步回主記憶體中

※一個新的變數只能在主記憶體中誕生,不允許在工作記憶體中直接使用一個未被初始化(load或assign)的變數。即就是對一個變數實施use和store操作之前,必須先執行assign和load操作。

※一個變數在同一時刻只允許一個執行緒對其進行lock操作,單lock操作可以被同一條執行緒重複執行多次,多次執行lock後,只有執行相同次數的unlock操作,變數才會被解鎖。lock和unlock必須成對出現。

※如果一個變數執行lock操作,將會請求工作記憶體中此變數的值,在執行引擎使用這個變數前需要重新執行load和asign操作初始化變數的值。

※如果一個變數事先沒有被lock操作鎖定,則不允許對它執行unlock操作,也不允許去unlock一個被其他執行緒鎖定的變數

※對一個變數執行unlock操作之前,必須先把此變數同步到主記憶體中(執行store和write操作)


更多關於Java記憶體模型中堆的講解請檢視http://www.importnew.com/14630.html