java并發(fā)編程 CPU緩存一致性協(xié)議MESI 的理解

本文沒有實(shí)例代碼,都是教科書似的知識(shí),但是知識(shí)特別重要! 所以要用心看,我會(huì)盡我最大輸出能力來寫。

CPU 高速緩存

計(jì)算機(jī)在執(zhí)行程序的時(shí)候,每條指令都是在 CPU 中執(zhí)行的,而執(zhí)行的時(shí)候,又免不了要和數(shù)據(jù)打交道。數(shù)據(jù)是存放在主存當(dāng)中的,也就是RAM (計(jì)算機(jī)的物理內(nèi)存)。

但是物理內(nèi)存速度遠(yuǎn)遠(yuǎn)是跟不是CPU執(zhí)行速度的,于是就在CPU層加上了「CPU 高速緩存」

CPU多級(jí)緩存

由于CPU的運(yùn)算速度遠(yuǎn)遠(yuǎn)超越了1級(jí)緩存的數(shù)據(jù)I\O能力,CPU廠商又引入了多級(jí)的緩存結(jié)構(gòu)。通常L1、L2 是每個(gè)CPU 核有一個(gè),L3 是多個(gè)核共用一個(gè)。

image.png

Cache Line

CPU多級(jí)緩存 是由很多個(gè)「緩存行」(Cache line) 組成的。Cache line 是 CPU多級(jí)緩存和 RAM 交換數(shù)據(jù)的最小單位。

帶有高速緩存的CPU執(zhí)行計(jì)算的流程

  1. 程序以及數(shù)據(jù)被加載到主內(nèi)存
  2. 指令和數(shù)據(jù)被加載到CPU的高速緩存
  3. CPU執(zhí)行指令,把結(jié)果寫到高速緩存
  4. 高速緩存中的數(shù)據(jù)寫回主內(nèi)存

緩存一致性

既然每個(gè)核中都有單獨(dú)的緩存,那我的 4 核 8 線程 CPU 處理主內(nèi)存數(shù)據(jù)的時(shí)候,不就會(huì)出現(xiàn)數(shù)據(jù)不一致問題了嗎?

為了解決這個(gè)問題,先后有過兩種方法:總線鎖機(jī)制和緩存鎖機(jī)制。

總線鎖就是使用 CPU 提供的一個(gè)LOCK#信號(hào),當(dāng)一個(gè)處理器在總線上輸出此信號(hào),其他處理器的請(qǐng)求將被阻塞,那么該處理器就可以獨(dú)占共享鎖。這樣就保證了數(shù)據(jù)一致性。

但是總線鎖開銷太大,我們需要控制鎖的粒度,所以又有了緩存鎖,核心就是“緩存一致性協(xié)議”,不同的 CPU 硬件廠商實(shí)現(xiàn)方式稍有不同,有MSI、MESI、MOSI等。

緩存鎖機(jī)制 MESI 協(xié)議

MSEI協(xié)議是多核cpu保證cache一致性的一種方法,他們有下面幾種狀態(tài):

  • M(Modified) : 緩存行是臟的(dirty),與主存RAM的值不同。如果別的CPU內(nèi)核要讀主存這塊數(shù)據(jù),該緩存行必須回寫到主存,狀態(tài)變?yōu)楣蚕?S)。

  • E(Exclusive) : 緩存行只在當(dāng)前緩存中,但是干凈的(clean) 緩存數(shù)據(jù)與主存RAM數(shù)據(jù)一致。當(dāng)別的緩存讀取它時(shí),狀態(tài)變?yōu)楣蚕?S);當(dāng)前寫數(shù)據(jù)時(shí),變?yōu)樾薷?M)。

  • S(Shared) : 緩存行也存在于其它緩存中且是干凈的。緩存行可以在任意時(shí)刻拋棄。

  • I(Invalid ) : 緩存行是無效的。

M-修改 E-獨(dú)占 S-共享 I-無效

假設(shè)有二核CPU A、B對(duì)應(yīng)三個(gè)緩存分別是cache 1、2。在主內(nèi)存中定義了a的值為0。

image.png

1. CPU 讀取數(shù)據(jù)的流程

  • CPU A發(fā)出讀取指令。
  • CPU A從RAM中通過bus總線讀取a到cache1中,并設(shè)置該cache line的狀態(tài)為E-獨(dú)占。
  • CPU B 試圖從RAM中讀取a時(shí),CPU A 檢測(cè)到了地址沖突。這時(shí)CPU A對(duì)相關(guān)數(shù)據(jù)做出響應(yīng)。此時(shí)a 存儲(chǔ)于cache 1和cache 2中,a在chche 1和cache 2中都被設(shè)置為S-共享。 【E-獨(dú)占 ===> S-共享】

2. CPU A 修改數(shù)據(jù)的流程

  • CPU A 計(jì)算完成發(fā)出指令要修改a。
  • CPU A 將a設(shè)置為 M-修改 并通知緩存了a的CPU B, CPU B將本地cache 2中的a設(shè)置為 I-無效,CPU B 要讀的話判斷是I-無效是就直接拿主存。
  • CPU A 對(duì)a進(jìn)行賦值。

3. CPU B 讀取數(shù)據(jù)的流程

  • CPU B 發(fā)出了要讀取a的指令。
  • CPU B 判斷是當(dāng)前是無效狀態(tài), 就通知 CPU A,CPU A將修改后的數(shù)據(jù)同步到主內(nèi)存時(shí) cache 1 修改為 E-獨(dú)占 , CPU B直接讀取主內(nèi)存并設(shè)置為 S-共享。

每個(gè)CPU讀取完緩存行之后都在內(nèi)存中監(jiān)聽已讀緩存行的狀態(tài),這時(shí)CPU b就會(huì)監(jiān)聽的緩存行a已被修改,此時(shí),CPU b就會(huì)把他設(shè)置為Invalid(無效)狀態(tài),無效狀態(tài)的數(shù)據(jù)會(huì)被丟棄,如果想繼續(xù)操作的話,還需要到主存中重新獲取。

參考資料
https://xie.infoq.cn/article/5f4397e93c26c89c9f7b144bf

《 圣人自知不自見;自愛不自貴 》
釋義:有自知之明,而且也不自我表現(xiàn);有自愛之心也不自顯高貴。

最后編輯于
?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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