Java內(nèi)存模型

java內(nèi)存模型(Java Memory Model,JMM)是java虛擬機(jī)規(guī)范定義的,用來(lái)屏蔽掉java程序在各種不同的硬件和操作系統(tǒng)對(duì)內(nèi)存的訪問(wèn)的差異,這樣就可以實(shí)現(xiàn)java程序在各種不同的平臺(tái)上都能達(dá)到內(nèi)存訪問(wèn)的一致性。可以避免像c++等直接使用物理硬件和操作系統(tǒng)的內(nèi)存模型在不同操作系統(tǒng)和硬件平臺(tái)下表現(xiàn)不同,比如有些c/c++程序可能在windows平臺(tái)運(yùn)行正常,而在linux平臺(tái)卻運(yùn)行有問(wèn)題。

MESI緩存協(xié)議

CPU高速緩存(Cache Memory)

CPU為何要有高速緩存?

CPU在摩爾定律的指導(dǎo)下以每18個(gè)月翻一番的速度在發(fā)展,然而內(nèi)存和硬盤的發(fā)展速度遠(yuǎn)遠(yuǎn)不及CPU。這就造成了高性能能的內(nèi)存和硬盤價(jià)格及其昂貴。然而CPU的高度運(yùn)算需要高速的數(shù)據(jù)。為了解決這個(gè)問(wèn)題,CPU廠商在CPU中內(nèi)置了少量的高速緩存以解決I\O速度和CPU運(yùn)算速度之間的不匹配問(wèn)題。

在CPU訪問(wèn)存儲(chǔ)設(shè)備時(shí),無(wú)論是存取數(shù)據(jù)抑或存取指令,都趨于聚集在一片連續(xù)的區(qū)域中,這就被稱為局部性原理。

* 時(shí)間局部性(Temporal Locality):如果一個(gè)信息項(xiàng)正在被訪問(wèn),那么在近期它很可能還會(huì)被再次訪問(wèn)。比如循環(huán)、遞歸、方法的反復(fù)調(diào)用等。

* 空間局部性(Spatial Locality):如果一個(gè)存儲(chǔ)器的位置被引用,那么將來(lái)他附近的位置也會(huì)被引用。比如順序執(zhí)行的代碼、連續(xù)創(chuàng)建的兩個(gè)對(duì)象、數(shù)組等。
帶有高速緩存的CPU執(zhí)行計(jì)算的流程
1.程序以及數(shù)據(jù)被加載到主內(nèi)存

2.指令和數(shù)據(jù)被加載到CPU的高速緩存

3.CPU執(zhí)行指令,把結(jié)果寫到高速緩存

4.高速緩存中的數(shù)據(jù)寫回主內(nèi)存

多核CPU多級(jí)緩存一致性協(xié)議MESI

多核CPU的情況下有多個(gè)一級(jí)緩存,如何保證緩存內(nèi)部數(shù)據(jù)的一致,不讓系統(tǒng)數(shù)據(jù)混亂。這里就引出了一個(gè)一致性的協(xié)議MESI。如下圖:

處理器、高數(shù)緩存、主內(nèi)存之間遵循一致性的協(xié)議交互關(guān)系.png
MESI協(xié)議緩存狀態(tài)

緩存行(Cache line):緩存存儲(chǔ)數(shù)據(jù)的單元
1.M修改,該Cache line有效,數(shù)據(jù)被修改了,和內(nèi)存中的數(shù)據(jù)不一致,數(shù)據(jù)只存在于本Cache中
2.E獨(dú)占,該Cache line有效,數(shù)據(jù)和內(nèi)存中的數(shù)據(jù)一致,數(shù)據(jù)只存在于本Cache中。
3.S共享,該Cache line有效,數(shù)據(jù)和內(nèi)存中的數(shù)據(jù)一致,數(shù)據(jù)存在于很多Cache中。
4.I無(wú)效,該Cache line無(wú)效。

JMM-8大原子操作

物理機(jī)高速緩存和主內(nèi)存之間的交互有協(xié)議,同樣的,java內(nèi)存中線程的工作內(nèi)存和主內(nèi)存的交互是由java虛擬機(jī)定義了如下的8種操作來(lái)完成的,每種操作必須是原子性的。java虛擬機(jī)中主內(nèi)存和工作內(nèi)存交互,就是一個(gè)變量如何從主內(nèi)存?zhèn)鬏數(shù)焦ぷ鲀?nèi)存中,如何把修改后的變量從工作內(nèi)存同步回主內(nèi)存。

1.lock (鎖定):作用于主內(nèi)存的變量,把一個(gè)變量標(biāo)記為一條線程獨(dú)占狀態(tài)
2.unlock (解鎖):作用于主內(nèi)存的變量,把一個(gè)處于鎖定狀態(tài)的變量釋放出來(lái),釋放后變量才可以被其他線程鎖定
3.read (讀取):把一個(gè)變量值從主存?zhèn)鬏數(shù)骄€程的工作內(nèi)存中,以便隨后的load動(dòng)作使用
4.load (載入):它把read操作從主內(nèi)存中得到的變量值放入工作的變量副本中
5.use (使用):把工作內(nèi)存中的一個(gè)變量值傳遞給執(zhí)行引擎
6.assign賦值):它把一個(gè)從執(zhí)行引擎接收到的值賦給工作內(nèi)存中的變量
7.store存儲(chǔ)):把工作內(nèi)存中的一個(gè)變量的值傳送到主存中
8.write寫入):把store操作從工作內(nèi)存中的一個(gè)變量的值傳送到主內(nèi)存的變量中

假設(shè)執(zhí)行以下代碼:

     var flag = false
    //線程1
     Thread {
        if (flag) {......}
    }
    //線程2
    Thread {
        flag = true
    }

以線程2為例,具體步驟:

1、執(zhí)行read操作,將數(shù)據(jù)從主內(nèi)存?zhèn)鬏數(shù)骄€程的工作內(nèi)存

2、執(zhí)行l(wèi)oad操作,主內(nèi)存中得到的變量值放入工作內(nèi)存的變量副本中

3、執(zhí)行use操作,工作內(nèi)存中的變量值傳遞給執(zhí)行引擎

4、執(zhí)行assign操作,把從執(zhí)行引擎接收到的值賦給工作內(nèi)存中的變量

5、執(zhí)行store操作,把工作內(nèi)存中的變量的值傳送到主存中

6、執(zhí)行write操作,把store操作從工作內(nèi)存中傳送的變量值更新主內(nèi)存的變量中

如下圖:


JMM原子操作示例.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • JMM定義了Java 虛擬機(jī)(JVM)在計(jì)算機(jī)內(nèi)存(RAM)中的工作方式。JVM是整個(gè)計(jì)算機(jī)虛擬模型,所以JMM是...
    JavaM閱讀 1,975評(píng)論 0 5
  • 一、現(xiàn)代計(jì)算機(jī)內(nèi)存模型 早期的計(jì)算機(jī)中由于CPU和內(nèi)存的速度是差不多的,所以CPU是直接訪問(wèn)內(nèi)存地址的。而在現(xiàn)代計(jì)...
    周二鴨閱讀 437評(píng)論 1 2
  • 1. 緩存一致性問(wèn)題 在我們學(xué)習(xí)java內(nèi)存模型之前,先來(lái)了解一下多核硬件架構(gòu)。 我們都知道計(jì)算執(zhí)行程序?qū)嶋H上是c...
    tracy_668閱讀 681評(píng)論 0 2
  • 1. 緩存一致性 計(jì)算機(jī)并發(fā)執(zhí)行若干任務(wù),需要與內(nèi)存交互。計(jì)算機(jī)存儲(chǔ)設(shè)備處理速度與處理器處理速度有著量級(jí)的差距,所...
    sizuoyi00閱讀 435評(píng)論 0 0
  • 在了解Java內(nèi)存模型之前,先來(lái)看一下多核硬件架構(gòu)。 我們應(yīng)該都知道,計(jì)算機(jī)在執(zhí)行程序的時(shí)候,每條指令都是在CPU...
    消失er閱讀 2,093評(píng)論 0 5

友情鏈接更多精彩內(nèi)容