概念
MESI是一種廣泛使用的寫回策略的緩存一致性協議。
MESI協議中的狀態
M: 被修改(Modified)
|
該緩存行只被緩存在該CPU的緩存中,並且是被修改過的(dirty),即與主存中的數據不一致,該緩存行中的內存需要在未來的某個時間點(允許其它CPU讀取請主存中相應內存之前)寫回(write back)主存。
當被寫回主存之后,該緩存行的狀態會變成獨享(exclusive)狀態。
|
E: 獨享的(Exclusive)
|
該緩存行只被緩存在該CPU的緩存中,它是未被修改過的(clean),與主存中數據一致。該狀態可以在任何時刻當有其它CPU讀取該內存時變成共享狀態(shared)。
同樣地,當CPU修改該緩存行中內容時,該狀態可以變成Modified狀態。
|
S: 共享的(Shared)
|
該狀態意味着該緩存行可能被多個CPU緩存,並且各個緩存中的數據與主存數據一致(clean),當有一個CPU修改該緩存行中,其它CPU中該緩存行可以被作廢(變成無效狀態(Invalid))。
|
I: 無效的(Invalid)
|
該緩存是無效的(可能有其它CPU修改了該緩存行)。
|
利用例子分析MESI的工作原理
利用對變量count自增的程序,來理解MESI的工作過程,明白多CPU下是如何進行數據寫回同步,保證數據的可見性,

具體CPU如何從主內存中加載變量進行運行的過程,在CPU緩存架構中有詳解,這里不做過多的解釋
1.假設CPU1率先搶到時間片,當變量count加載至CPU緩存中時,會將count的使用標志為(E獨占:首次加載會將變量置為獨占,也就說明沒有其他CPU進行加載)
2.CPU2也獲得時間片,把變量count加載緩存中,此時count的使用標志為(E獨占),並發送消息至總線,告知其他CPU讀取了變量的值,各CPU通過時刻監聽(總線嗅探機制)獲得到此變量已被多個CPU所加載,那么此時CPU2就會將自身count的使用標志置為(S共享),CPU1也會將變量的使用標志也會置為(S)
3.CPU1從緩存中加載count至寄存器中進行自增操作,執行完畢之后,count = 0 -> 1,此時由於count的值發生了變化,因此CPU1中變量count使用標志應為(M修改),此時CPU1會發送消息至總線,告知其他線程已經修改了變量count 的值,其他CPU嗅探到值的修改,就會將自身變量count的使用標志置為(I無效)
4.CPU1會將M狀態的變量立刻寫回至主內存中,寫回完畢之后,CPU1會將使用狀態置為(E獨享),發送消息至總線,告知其他CPU已經寫回完畢,其他CPU會再此從主內存中讀取變量count的值,讀取完畢之后,也會發送消息至總線,其他CPU嗅探到之后將自身變量count置為(S共享),自身變量的使用狀態也會置為(S共享)
存在的疑問:
多個CPU同時都將變量置為M修改狀態,那怎么辦?
首先多個CPU都想將變量置為M修改狀態,那么系統會有裁決機制,保證只有一個CPU能夠操作成功,因此不會存在多個M狀態的數據
MESI操作的基本單位:緩存行(CPU緩存中的最小存儲單元)
緩存行的最小存儲單元大小:32bit,64bit,128bit(因系統而定)
機械硬盤的最小存儲單元:簇
MESI緩存一致性協議失效的原因
緩存一致性協議失效的后果:當MESI失效之后,那么系統會自動將啟用總線加鎖機制,那么執行效率則會大打折扣。
失效的情況:
1.當緩存行存儲的數據超過最小存儲單元大小時(數據長度存儲跨越多個緩存行的情況),就會導致MESI操作緩存行無效,導致MESI緩存一致性協議失效;
2.系統不支持緩存一致性協議。
緩存行的概念:多個數據可以存儲在一個緩存行,一個數據可以存儲在多個緩存行(此種情況會導致MESI失效)
總線加鎖機制
對主內存數據進行加鎖和解鎖操作,當加鎖之后,此數據不允許其他線程進行讀寫,只能等加鎖線程操作完畢進行解鎖之后才能進行操作。
Java中volatile關鍵詞保證可見性原理
MESI緩存一致性協議底層是通過#Lock的指令進行觸發的,而volatile關鍵詞修飾之后的變量,編譯為指令集執行是,會加上#Lock進行修飾,用來觸發緩存一致性協議,而且#Lock指令修飾之后,置為M(修改狀態)的變量,會強制立刻寫入主內存中,並且發送消息至總線,其他加載此變量的線程,就會將工作內存中變量的使用狀態修改為I(無效狀態),此時線程就被迫需要重新從主內存中讀取該變量的值,這就是volatile關鍵詞保證可見性的原因。