MESI是一種廣泛使用的寫回策略的緩存一致性協(xié)議看靠。
MESI協(xié)議中的狀態(tài)
M:Modified被修改
E:Exclusive獨(dú)享的
S:Shared共享的
I:Invalid無(wú)效的
M: 被修改(Modified) 該緩存行只被緩存在該CPU的緩存中赂毯,并且是被修改過的(dirty),即與主存中的數(shù)據(jù)不一致固灵,該緩存行中的內(nèi)存需要在未來(lái)的某個(gè)時(shí)間點(diǎn)(允許其它CPU讀取請(qǐng)主存中相應(yīng)內(nèi)存之前)寫回(write back)主存汽畴。當(dāng)被寫回主存之后,該緩存行的狀態(tài)會(huì)變成獨(dú)享(exclusive)狀態(tài)颠黎。
E: 獨(dú)享的(Exclusive) 該緩存行只被緩存在該CPU的緩存中赵哲,它是未被修改過的(clean),與主存中數(shù)據(jù)一致俊柔。該狀態(tài)可以在任何時(shí)刻當(dāng)有其它CPU讀取該內(nèi)存時(shí)變成共享狀態(tài)(shared)筹麸。同樣地,當(dāng)CPU修改該緩存行中內(nèi)容時(shí)雏婶,該狀態(tài)可以變成Modified狀態(tài)竹捉。
S: 共享的(Shared) 該狀態(tài)意味著該緩存行可能被多個(gè)CPU緩存,并且各個(gè)緩存中的數(shù)據(jù)與主存數(shù)據(jù)一致(clean)尚骄,當(dāng)有一個(gè)CPU修改該緩存行中块差,其它CPU中該緩存行可以被作廢(變成無(wú)效狀態(tài)(Invalid))。
I: 無(wú)效的(Invalid) 該緩存是無(wú)效的(可能有其它CPU修改了該緩存行)倔丈。
一個(gè)例子來(lái)分析MESI的工作原理
利用對(duì)變量count自增的程序憨闰,來(lái)理解MESI的工作過程,明白多CPU下是如何進(jìn)行數(shù)據(jù)寫回同步需五,保證數(shù)據(jù)的可見性鹉动,
1.假設(shè)CPU1率先搶到時(shí)間片,當(dāng)變量count加載至CPU緩存中時(shí)宏邮,會(huì)將count的使用標(biāo)志為(E獨(dú)占:首次加載會(huì)將變量置為獨(dú)占泽示,也就說(shuō)明沒有其他CPU進(jìn)行加載)
2.CPU2也獲得時(shí)間片,把變量count加載緩存中蜜氨,此時(shí)count的使用標(biāo)志為(E獨(dú)占)械筛,并發(fā)送消息至總線,告知其他CPU讀取了變量的值飒炎,各CPU通過時(shí)刻監(jiān)聽(總線嗅探機(jī)制)獲得到此變量已被多個(gè)CPU所加載埋哟,那么此時(shí)CPU2就會(huì)將自身count的使用標(biāo)志置為(S共享),CPU1也會(huì)將變量的使用標(biāo)志也會(huì)置為(S)
3.CPU1從緩存中加載count至寄存器中進(jìn)行自增操作郎汪,執(zhí)行完畢之后赤赊,count = 0 -> 1闯狱,此時(shí)由于count的值發(fā)生了變化,因此CPU1中變量count使用標(biāo)志應(yīng)為(M修改)抛计,此時(shí)CPU1會(huì)發(fā)送消息至總線哄孤,告知其他線程已經(jīng)修改了變量count 的值,其他CPU嗅探到值的修改吹截,就會(huì)將自身變量count的使用標(biāo)志置為(I無(wú)效)
4.CPU1會(huì)將M狀態(tài)的變量立刻寫回至主內(nèi)存中录豺,寫回完畢之后,CPU1會(huì)將使用狀態(tài)置為(E獨(dú)享)饭弓,發(fā)送消息至總線双饥,告知其他CPU已經(jīng)寫回完畢,其他CPU會(huì)再此從主內(nèi)存中讀取變量count的值弟断,讀取完畢之后咏花,也會(huì)發(fā)送消息至總線,其他CPU嗅探到之后將自身變量count置為(S共享)阀趴,自身變量的使用狀態(tài)也會(huì)置為(S共享)
那么如果多個(gè)CPU同時(shí)都將變量置為M修改狀態(tài)昏翰,那怎么辦?首先多個(gè)CPU都想將變量置為M修改狀態(tài)刘急,那么系統(tǒng)會(huì)有裁決機(jī)制棚菊,保證只有一個(gè)CPU能夠操作成功,因此不會(huì)存在多個(gè)M狀態(tài)的數(shù)據(jù)
MESI操作的基本單位:緩存行(CPU緩存中的最小存儲(chǔ)單元)
緩存行的最小存儲(chǔ)單元大惺逯:32bit统求,64bit,128bit(因系統(tǒng)而定)
機(jī)械硬盤的最小存儲(chǔ)單元:簇
MESI緩存一致性協(xié)議失效的原因
緩存一致性協(xié)議失效的后果:當(dāng)MESI失效之后据块,那么系統(tǒng)會(huì)自動(dòng)將啟用總線加鎖機(jī)制码邻,那么執(zhí)行效率則會(huì)大打折扣。
失效的情況:
1.當(dāng)緩存行存儲(chǔ)的數(shù)據(jù)超過最小存儲(chǔ)單元大小時(shí)(數(shù)據(jù)長(zhǎng)度存儲(chǔ)跨越多個(gè)緩存行的情況)另假,就會(huì)導(dǎo)致MESI操作緩存行無(wú)效像屋,導(dǎo)致MESI緩存一致性協(xié)議失效;
2.系統(tǒng)不支持緩存一致性協(xié)議边篮。
緩存行的概念:多個(gè)數(shù)據(jù)可以存儲(chǔ)在一個(gè)緩存行己莺,一個(gè)數(shù)據(jù)可以存儲(chǔ)在多個(gè)緩存行(此種情況會(huì)導(dǎo)致MESI失效)
總線加鎖機(jī)制
對(duì)主內(nèi)存數(shù)據(jù)進(jìn)行加鎖和解鎖操作,當(dāng)加鎖之后戈轿,此數(shù)據(jù)不允許其他線程進(jìn)行讀寫凌受,只能等加鎖線程操作完畢進(jìn)行解鎖之后才能進(jìn)行操作。
Java中volatile關(guān)鍵字保證可見性原理
MESI緩存一致性協(xié)議底層是通過#Lock的指令進(jìn)行觸發(fā)的凶杖,
而volatile關(guān)鍵詞修飾之后的變量胁艰,編譯為指令時(shí)會(huì)加上#Lock修飾,用來(lái)觸發(fā)緩存一致性協(xié)議智蝠,而且#Lock指令修飾之后腾么,置為M(修改狀態(tài))的變量,會(huì)強(qiáng)制立刻寫入主內(nèi)存中杈湾,并且發(fā)送消息至總線解虱,其它加載此變量的線程,就會(huì)將工作內(nèi)存中變量的使用狀態(tài)修改為I(無(wú)效狀態(tài))漆撞,此時(shí)線程就被迫重新從主內(nèi)存中讀取該變量的值殴泰,這就是volatile關(guān)鍵詞保證可見性的原因。
volatile是Java虛擬機(jī)提供的輕量級(jí)的同步機(jī)制浮驳,它具備兩種特性:保證共享變量對(duì)所有線程的可見性悍汛;禁止指令重排序,保證有序性至会;無(wú)法保證原子性(像count++就不是原子操作离咐,包含了讀 自加操作)