[Java多線程編程之四] CPU緩存和內(nèi)存屏障

一辛慰、CPU三級緩存

1区匠、緩存的作用

??CPU的結(jié)構(gòu)很復(fù)雜,簡單地說由運算器和寄存器組成。程序運行時驰弄,需要CPU去執(zhí)行運算麻汰,運算是由運算器來執(zhí)行,運算器可以做加減乘除運算以及與或非邏輯運算戚篙,運算過程中可能需要臨時存放數(shù)據(jù)到某個地方五鲫,寄存器就起到這個作用。



??雖然寄存器可以存儲一些運行時數(shù)據(jù)岔擂,但是容量是很小的位喂,程序運行時產(chǎn)生的大部分?jǐn)?shù)據(jù)(比如Java對象)是存儲在內(nèi)存中的,并且程序指令也是存儲在內(nèi)存中乱灵,所以程序運行時CPU需要頻繁操作內(nèi)存塑崖,包括讀取和寫入,但是CPU的速度太快了阔蛉,如果直接操作內(nèi)存弃舒,CPU的大部分時間會處于等待內(nèi)存操作的空轉(zhuǎn)狀態(tài)癞埠,內(nèi)存完全跟不上節(jié)奏状原,怎么辦?



??這時候就需要有緩存的存在了苗踪,內(nèi)存將CPU要讀取的數(shù)據(jù)源源不斷地加載到緩存中颠区,CPU讀取緩存,緩存的速度比內(nèi)存快多了通铲,勉強(qiáng)能跟得上CPU大哥的節(jié)奏了毕莱!

??但是CPU表示緩存你還是太慢了,我?guī)Р粍勇幔援a(chǎn)生了一級緩存朋截、二級緩存、三級緩存吧黄,一級緩存最快部服、二級次之、三級最慢拗慨;緩存容量則反過來廓八,一級最小,二級大一些赵抢,三級最大剧蹂。
??為什么緩存能加快系統(tǒng)運行?舉個例子烦却,現(xiàn)在需要很多水宠叼,如果直接打開水龍頭,要放很久其爵,如果有水桶已經(jīng)放滿了水车吹,取水是不是會快點筹裕?如果需要更多的水,我們弄個水塔窄驹,平時儲滿水朝卒,假如水桶的水不夠用,則打開水塔乐埠,這樣就達(dá)到快速取水的目的抗斤。
??緩存可以看成是一個數(shù)據(jù)的池子,由于速度越快的緩存單位存儲空間的價格也越高丈咐,所以要有多級緩存瑞眼,速度快的存儲小,速度慢的存儲大棵逊,多級緩存結(jié)合達(dá)到總體上經(jīng)濟(jì)又實惠的效果伤疙,在三級緩存中,每一級緩存都有80%左右的命中率辆影,如果本級緩存中找不到CPU要的數(shù)據(jù)徒像,則進(jìn)入下一級緩存中查找,三級緩存中找不到則進(jìn)入內(nèi)存查找蛙讥,這種可能性只有0.8%锯蛀,大多數(shù)情況下可以保證了CPU快速運行,避免內(nèi)存延遲次慢。


CPU讀取數(shù)據(jù)順序
  • L1 Cahce(一級緩存)是CPU第一層高速緩存旁涤,分為數(shù)據(jù)緩存和指令緩存,一般服務(wù)器CPU的L1緩存的容量通常在32-4096KB迫像。
  • L2 是由于L1高速緩存容量的限制劈愚,為了再次提高CPU的運算速度,在CPU外部放置一高速存儲器闻妓,即二級緩存菌羽。
  • L3 緩存的應(yīng)用可以進(jìn)一步降低內(nèi)存延遲,同時提升大數(shù)據(jù)量計算時處理器的性能纷闺;具有較大L3緩存的處理器可以提供更有效的文件系統(tǒng)緩存行為及較短信息和處理器隊列長度算凿;現(xiàn)在的計算機(jī)都內(nèi)置了L3,并且多核計算機(jī)中多個CPU可以共享一個L3緩存犁功,但是每個CPU都會有它自己的L1氓轰、L2。


    CPU緩存設(shè)計示意圖

??CPU在讀取數(shù)據(jù)時浸卦,先在L1中尋找署鸡,再從L2尋找,再從L3尋找,然后是內(nèi)存靴庆,最后是外存儲器时捌。

2、緩存同步協(xié)議

??對于多核計算機(jī)炉抒,多個CPU可能會讀取同樣的數(shù)據(jù)進(jìn)行緩存奢讨,在經(jīng)過不同運算之后,最終寫入主內(nèi)存焰薄,那么問題來了拿诸,寫入的時候誰先誰后,最終寫入主內(nèi)存中的數(shù)據(jù)以哪個CPU為準(zhǔn)塞茅?
??為了應(yīng)對這種高速緩存回寫的場景亩码,眾多CPU廠商聯(lián)合制定了緩存一致性協(xié)議MESI協(xié)議,并分別實現(xiàn)野瘦,MESI協(xié)議規(guī)定每條緩存有個狀態(tài)位描沟,同時定義了下面四個狀態(tài):

  • 修改態(tài)(Modified)- 此cache行已被修改過(臟行),內(nèi)容已不同于主存鞭光,為此cache專有吏廉;
  • 專有態(tài)(Exclusive)- 此cache行內(nèi)容同于主存,但不出現(xiàn)于其他cache中衰猛;
  • 共享態(tài)(Shared)- 此cache行內(nèi)容同于主存迟蜜,但也出現(xiàn)于其他cache中刹孔;
  • 無效態(tài)(Invalid)- 此cache行內(nèi)容無效(空行)啡省。

??當(dāng)計算機(jī)中有多個處理器時,單個CPU對緩存中數(shù)據(jù)進(jìn)行了改動髓霞,需要通知給其他CPU卦睹;這意味著CPU不僅要控制自己的讀寫操作,還要監(jiān)聽其他CPU發(fā)出的通知方库,從而保證最終一致结序,所以在MESI協(xié)議下不存在 “可見性” 問題。


二纵潦、CPU緩存模型

??緩存一致性協(xié)議可以保證CPU緩存一致徐鹤,但是對性能有很大的消耗,因此CPU的架構(gòu)師在計算單元和L1之前又增加了 Store Buffer邀层、Load Buffer返敬,如下所示:


加了 Store Buffer 和 Load Buffer 的 CPU 緩存體系

??L1、L2寥院、L3和主內(nèi)存之間是同步的劲赠,這是通過緩存一致性協(xié)議來保證的,但是 Store Buffer、Load Buffer 和L1之間卻是異步的凛澎。也就是說霹肝,往內(nèi)存中寫入一個變量,這個變量會保存在 Store Buffer 里面塑煎,稍后才異步寫入L1中沫换,同時同步寫入主內(nèi)存中。

??從操作系統(tǒng)內(nèi)核的角度最铁,緩存模型可以被簡化為如下圖所示:


操作系統(tǒng)內(nèi)核視角下的 CPU 緩存模型

??多 CPU苗沧,每個 CPU 多核,每個核上面可能還有多個硬件線程炭晒,對于操作系統(tǒng)來講待逞,就相當(dāng)于一個個的邏輯 CPU。每個邏輯 CPU 都有自己的緩存网严,這些緩存和主內(nèi)存之間不是完全同步的识樱。

??對應(yīng)到 Java 里,就是 JVM 抽象內(nèi)存模型震束,如下:

JVM抽象內(nèi)存模型



三怜庸、重排序

3.1 分類

3.1.1 編譯器重排序

??對沒有先后依賴關(guān)系的語句,編譯器可以重新調(diào)整語句的執(zhí)行順序垢村。

3.1.2 CPU指令重排序

??在指令級別割疾,讓沒有依賴關(guān)系的多條指令并行。

??運行時指令重排是CPU為了避免阻塞等待某些操作需要的資源嘉栓,先去執(zhí)行可執(zhí)行的指令宏榕,當(dāng)阻塞等待的資源獲取到時,再去執(zhí)行對應(yīng)的指令的操作侵佃。

?? 代碼示例:


指令重排序

??指令重排的場景:當(dāng)CPU寫緩存時發(fā)現(xiàn)緩存區(qū)塊正在被其他CPU占用麻昼,為了提高CPU處理性能,可能將后面的讀緩存命令優(yōu)先執(zhí)行馋辈。

3.1.3 CPU內(nèi)存重排序

??CPU 有自己的緩存抚芦,指令的執(zhí)行順序和寫入主內(nèi)存的順序不完全一致,這是造成內(nèi)存可見性問題的主要原因迈螟,因為按照執(zhí)行順序叉抡,讀寫都是在 Load Buffer 和 Store Buffer 中完成的,緩存中的數(shù)據(jù)不會馬上同步到主內(nèi)存中去答毫,因此數(shù)據(jù)同步到主內(nèi)存中的順序可能跟指令執(zhí)行的順序不一致褥民,最終造成 “內(nèi)存可見性” 問題。

3.2 as-if-serial

??不管怎么重排序(編譯器和處理器為了提高并行度)烙常,單線程程序的執(zhí)行結(jié)果不能被改變轴捎,編譯器鹤盒、runtime和處理器都必須遵循as-if-serial語義,也就是說侦副,編譯器和處理器不會對存在數(shù)據(jù)依賴關(guān)系的操作做重排序侦锯。


3.3 指令重排存在問題

??但是對多線程程序來說,指令邏輯無法分辨因果關(guān)聯(lián)秦驯,因此指令重排可能會出現(xiàn)亂序執(zhí)行尺碰,導(dǎo)致程序運行結(jié)果錯誤,因此在多線程程序中有些時候需要通類似 volatile 修飾變量之類的方式來禁止可能導(dǎo)致可見性問題的指令重排译隘。


四亲桥、內(nèi)存屏障

??為了禁止編譯器重排序和 CPU 重排序,在編譯器和 CPU 層面都有對應(yīng)的指令固耘,也就是內(nèi)存屏障(Memory Barrier)题篷,這也正是 JMM 和 happen-before 規(guī)則的底層實現(xiàn)原理。

??處理器提供了兩個內(nèi)存屏障指令:

1厅目、寫內(nèi)存屏障(Store Memory Barrier)

??在指令后插入Store Barrier番枚,能讓寫入緩存中的最新數(shù)據(jù)更新寫入主內(nèi)存,讓其他線程可見损敷;當(dāng)發(fā)生這種強(qiáng)制寫入主內(nèi)存的顯式調(diào)用葫笼,CPU就不會處于性能優(yōu)化考慮進(jìn)行指令重排。

2拗馒、讀內(nèi)存屏障(Load Memory Barrier)

??在指令前插入Load Barrier路星,可以讓高速緩存中的數(shù)據(jù)失效,強(qiáng)制重新從主內(nèi)存加載數(shù)據(jù)诱桂,讓CPU緩存與主內(nèi)存保持一致洋丐,避免緩存導(dǎo)致的一致性問題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末访诱,一起剝皮案震驚了整個濱河市垫挨,隨后出現(xiàn)的幾起案子韩肝,更是在濱河造成了極大的恐慌触菜,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哀峻,死亡現(xiàn)場離奇詭異涡相,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)剩蟀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門催蝗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人育特,你說我怎么就攤上這事丙号∠入” “怎么了?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵犬缨,是天一觀的道長喳魏。 經(jīng)常有香客問我,道長怀薛,這世上最難降的妖魔是什么抛计? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任捡遍,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捉貌。我一直安慰自己,他們只是感情好媒鼓,可當(dāng)我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布梦鉴。 她就那樣靜靜地躺著,像睡著了一般十电。 火紅的嫁衣襯著肌膚如雪念搬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天摆出,我揣著相機(jī)與錄音朗徊,去河邊找鬼。 笑死偎漫,一個胖子當(dāng)著我的面吹牛爷恳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播象踊,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼温亲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了杯矩?” 一聲冷哼從身側(cè)響起栈虚,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎史隆,沒想到半個月后魂务,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡泌射,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年粘姜,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熔酷。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡孤紧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拒秘,到底是詐尸還是另有隱情号显,我是刑警寧澤臭猜,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站押蚤,受9級特大地震影響获讳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜活喊,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一丐膝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧钾菊,春花似錦帅矗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至滞详,卻和暖如春凛俱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背料饥。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工蒲犬, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人岸啡。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓原叮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親巡蘸。 傳聞我的和親對象是個殘疾皇子奋隶,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容