你真的瞭解JMM嗎?
引言
在現代計算機中,cpu的指令速度遠超記憶體的存取速度,由於計算機的儲存裝置與處理器的運算速度有幾個數量級的差距,所以現代計算機系統都不得不加入一層讀寫速度儘可能接近處理器運算速度的快取記憶體(Cache)來作為記憶體與處理器之間的緩衝:將運算需要使用到的資料複製到快取中,讓運算能快速進行,當運算結束後再從快取同步回記憶體之中,這樣處理器就無須等待緩慢的記憶體讀寫了。
基於快取記憶體的儲存互動很好地解決了處理器與記憶體的速度矛盾,但是也為計算機系統帶來更高的複雜度,因為它引入了一個新的問題:快取一致性(Cache Coherence)。在多處理器系統中,每個處理器都有自己的快取記憶體,而它們又共享同一主記憶體(MainMemory)。當多個處理器的運算任務都涉及同一塊主記憶體區域時,將可能導致各自的快取資料不一致,舉例說明變數在多個CPU之間的共享。如果真的發生這種情況,那同步回到主記憶體時以誰的快取資料為準呢?為瞭解決一致性的問題,需要各個處理器訪問快取時都遵循一些協議,在讀寫時要根據協議來進行操作,這類協議有MSI、MESI(Illinois Protocol)、MOSI、Synapse、Firefly及Dragon Protocol等。
一、JMM(Java Memory Model)
java虛擬機器器規範定義java記憶體模型遮蔽掉各種硬體和作業系統的記憶體訪問差異,以實現讓java程式在各種平臺下都能達到一致的併發效果。
java記憶體模型規定了一個執行緒如何和何時可以看到由其他執行緒修改過後的共享變數的值,以及在必須時如何同步的訪問共享變數。
注意:我們這裡強調的是共享變數,不是私有變數。
java記憶體模型規定了所有的變數都儲存在主記憶體中(JVM記憶體的一部分)。每條執行緒都有自己的工作記憶體,工作記憶體中儲存了該執行緒使用的主記憶體中共享變數的副本,執行緒對變數的所有操作(讀取、賦值等)都必須在工作記憶體中進行,而不能直接讀寫主記憶體中的變數;工作記憶體線上程間是隔離的,不能直接訪問對方工作記憶體中的變數。所以在多執行緒操作共享變數時,就通過JMM來進行控制。
我們來看一看執行緒,工作記憶體、主記憶體三者的互動關係圖。