匯流排鎖 快取鎖 MESI

2021-08-28 07:55:12 字數 2254 閱讀 7655

隨著多核時代的到來,併發操作已經成了很正常的現象,作業系統必須要有一些機制和原語,以保證某些基本操作的原子性,比如處理器需要保證讀乙個位元組或寫乙個位元組是原子的,那麼它是如何實現的呢?有兩種機制:匯流排鎖定和快取一致性

我們知道,cpu和物理記憶體之間的通訊速度遠慢於cpu的處理速度,所以cpu有自己的內部快取,根據一些規則將記憶體中的資料讀取到內部快取中來,以加快頻繁讀取的速度。我們假設在一台pc上只有乙個cpu和乙份內部快取,那麼所有程序和執行緒看到的數都是快取裡的數,不會存在問題;但現在伺服器通常是多 cpu,更普遍的是,每塊cpu裡有多個核心,而每個核心都維護了自己的快取,那麼這時候多執行緒併發就會存在快取不一致性,這會導致嚴重問題。

以 i++為例,i的初始值是0.那麼在開始每塊快取都儲存了i的值0,當第一塊核心做i++的時候,其快取中的值變成了1,即使馬上回寫到主記憶體,那麼在回寫之後第二塊核心快取中的i值依然是0,其執行i++,回寫到記憶體就會覆蓋第一塊核心的操作,使得最終的結果是1,而不是預期中的2.

那麼怎麼解決整個問題呢?作業系統提供了匯流排鎖定的機制。前端匯流排(也叫cpu匯流排)是所有cpu與晶元組連線的主幹道,負責cpu與外界所有部件的通訊,包括快取記憶體、記憶體、北橋,其控制匯流排向各個部件傳送控制訊號、通過位址匯流排傳送位址訊號指定其要訪問的部件、通過資料匯流排雙向傳輸。在cpu1要做 i++操作的時候,其在匯流排上發出乙個lock#訊號,其他處理器就不能操作快取了該共享變數記憶體位址的快取,也就是阻塞了其他cpu,使該處理器可以獨享此共享記憶體。

但我們只需要對此共享變數的操作是原子就可以了,而匯流排鎖定把cpu和記憶體的通訊給鎖住了,使得在鎖定期間,其他處理器不能操作其他記憶體位址的資料,從而開銷較大,所以後來的cpu都提供了快取一致性機制,intel的奔騰486之後就提供了這種優化。

快取一致性:快取一致性機制就整體來說,是當某塊cpu對快取中的資料進行操作了之後,就通知其他cpu放棄儲存在它們內部的快取,或者從主記憶體中重新讀取,用mesi闡述原理如下:

mesi

協議:是以快取行(快取的基本資料單位,在intel的cpu上一般是64位元組)的幾個狀態來命名的(全名是modified、exclusive、 share or invalid)。該協議要求在每個快取行上維護兩個狀態位,使得每個資料單位可能處於m、e、s和i這四種狀態之一,各種狀態含義如下:

m:被修改的。處於這一狀態的資料,只在本cpu中有快取資料,而其他cpu中沒有。同時其狀態相對於記憶體中的值來說,是已經被修改的,且沒有更新到記憶體中。

e:獨佔的。處於這一狀態的資料,只有在本cpu中有快取,且其資料沒有修改,即與記憶體中一致。

s:共享的。處於這一狀態的資料在多個cpu中都有快取,且與記憶體一致。

i:無效的。本cpu中的這份快取已經無效。

乙個處於m狀態的快取行,必須時刻監聽所有試圖讀取該快取行對應的主存位址的操作,如果監聽到,則必須在此操作執行前把其快取行中的資料寫回cpu。

乙個處於s狀態的快取行,必須時刻監聽使該快取行無效或者獨享該快取行的請求,如果監聽到,則必須把其快取行狀態設定為i。

乙個處於e狀態的快取行,必須時刻監聽其他試圖讀取該快取行對應的主存位址的操作,如果監聽到,則必須把其快取行狀態設定為s。

當cpu需要讀取資料時,如果其快取行的狀態是i的,則需要從記憶體中讀取,並把自己狀態變成s,如果不是i,則可以直接讀取快取中的值,但在此之前,必須要等待其他cpu的監聽結果,如其他cpu也有該資料的快取且狀態是m,則需要等待其把快取更新到記憶體之後,再讀取。

當cpu需要寫資料時,只有在其快取行是m或者e的時候才能執行,否則需要發出特殊的rfo指令(read or ownership,這是一種匯流排事務),通知其他cpu置快取無效(i),這種情況下效能開銷是相對較大的。在寫入完成後,修改其快取狀態為m。

所以如果乙個變數在某段時間只被乙個執行緒頻繁地修改,則使用其內部快取就完全可以辦到,不涉及到匯流排事務,如果快取一會被這個cpu獨佔、一會被那個cpu 獨佔,這時才會不斷產生rfo指令影響到併發效能。這裡說的快取頻繁被獨佔並不是指執行緒越多越容易觸發,而是這裡的cpu協調機制,這有點類似於有時多執行緒並不一定提高效率,原因是執行緒掛起、排程的開銷比執行任務的開銷還要大,這裡的多cpu也是一樣,如果在cpu間排程不合理,也會形成rfo指令的開銷比任務開銷還要大。當然,這不是程式設計者需要考慮的事,作業系統會有相應的記憶體位址的相關判斷

並非所有情況都會使用快取一致性的,如被操作的資料不能被快取在cpu內部或運算元據跨越多個快取行(狀態無法標識),則處理器會呼叫匯流排鎖定;另外當cpu不支援快取鎖定時,自然也只能用匯流排鎖定了,比如說奔騰486以及更老的cpu。

快取設計,LIRS,cache鎖粒度

網際網路架構中快取無處不在,某廠牛人曾經說過 快取就像清涼油,不舒服,抹一下就好了 高品質的儲存容量小,高 低品質儲存容量大,低,快取的目的就在於 擴充 高品質儲存的容量。本文 快取相關的一些問題。lru替換演算法 快取的技術點包括記憶體管理和替換演算法。lru是使用最多的替換演算法,每次淘汰最久沒...

鎖 JDK鎖 redis鎖 mysql鎖

在減庫存的 外麵包一層synchronized public string deductstock else 雙重檢查單例模式 public class singletontype6 public static singletontype6 getinstance return instance 利...

互斥鎖 自旋鎖 讀寫鎖 悲觀鎖 樂觀鎖

最底層的兩種就是會 互斥鎖和自旋鎖 有很多高階的鎖都是基於它們實現的,你可以認為它們是各種鎖的地基,所以我們必須清楚它倆之間的區別和應用。加鎖的目的就是保證共享資源在任意時間裡,只有乙個執行緒訪問,這樣就可以避免多執行緒導致共享資料錯亂的問題。當已經有乙個執行緒加鎖後,其他執行緒加鎖則就會失敗,互斥...