MESI緩存一致性協議
現在CPU都是多核cpu,且擁有多級緩存,如下圖的CPU緩存模型
目前的CPU都是多核心的,每個核心都有自己的L1、L2緩存,當多個CPU同時操作同一份數據,就會出現緩存不一致的問題。
有兩種解決方法:
- 總線鎖定
- 緩存一致性協議(總線嗅探機制)
第一種的話,如果cpu某核要做i++操作,會向總線上發出一個LOCK#信號,阻塞了其他cpu,鎖定期間開銷較大,所以一般不采用這種方法。
此時,MESI緩存一致性協議應運而生,分為四種狀態
各種狀態含義如下:
M:被修改的。處於這一狀態的數據,只在本CPU中有緩存數據,而其他CPU中沒有。同時其狀態相對於內存中的值來說,是已經被修改的,且沒有更新到內存中。
E:獨占的。處於這一狀態的數據,只有在本CPU中有緩存,且其數據沒有修改,即與內存中一致。
S:共享的。處於這一狀態的數據在多個CPU中都有緩存,且與內存一致。
I:無效的。本CPU中的這份緩存已經無效。
值得注意的是,TSO內存模型后來引入了storebuffer,變成如下
因為MESI緩存一致性協議,所以L1,L2,L3等CPU多級緩存被抽象成cache,那么為什么要加入storebuffer
原因:
- 如cpuA核要修改本地緩存,那么就需要將invalid狀態發送給其他擁有該緩存數據的CPU緩存中,這過程會阻塞處理器,而storebuffer的出現,可以讓處理器做其他事情,不會阻塞,等到收到所有的應答,才把storebuffer的數據更新到主存中。
使用storebuffer有風險,因為不能保證數據何時保存,而storebuffer中如果有值,處理器會優先讀取sb中的值。
從上面可以看出,MESI緩存一致性協議其實是保證了抽象cache的緩存一致性,而java中的volatile其實是通過內存屏障保證處理器到sb到L1緩存中間的防止指令的重排序導致不確定結果。
同時,volatile是java語言層面給出的保證,MESI緩存一致性協議只適用於L1/L2/L3 cache中,在storebuffer等影響下,仍然有重排序產生.
分析得比較淺顯,本文僅僅是為自己復習起到拋磚引玉的作用。