<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          JUC并發(fā)編程之MESI緩存一致協(xié)議詳解

          共 3088字,需瀏覽 7分鐘

           ·

          2021-05-14 16:46

          點擊上方藍字 關(guān)注我吧



          1
          前言

          經(jīng)過幾篇文章,我一直在講到并發(fā)下可能會導致很多問題的發(fā)生,通過volatile又能解決它的可見性和指令重排問題,在閱讀我的文章的時候,不知道大家伙是否好奇過在計算機底層,它是如何保證數(shù)據(jù)的安全性的,volatile為什么能夠解決這些問題?那么該文章就來用為簡潔的話語來解釋MESI協(xié)議。


          2
          為什么需要緩存一致性協(xié)議


          在前面JMM內(nèi)存模型文章中,我有寫到多個線程并發(fā)訪問一個主內(nèi)存的共享變量時,這些線程會在各自的工作內(nèi)存中拷貝一份共享變量的副本,那么這就帶來了一個問題,一個線程對共享變量進行修改后,其他的線程該如何感知到共享變量的改變從而做出適當?shù)姆磻?yīng),確保后續(xù)線程讀取這個共享變量的時候,總是最新的值,從而防止出現(xiàn)臟數(shù)據(jù)的情況。說到這,就不得不說一下緩存一致性的由來。


          3
          緩存一致性的由來


          首先我這里放上一張CPU內(nèi)核簡易結(jié)構(gòu)圖


          在最初的CPU都是單核心,然而在CPU的高速發(fā)展下,有那么一段話,CPU發(fā)展的速度有一個摩爾定律,幾乎每過18個月就會更新一次,而內(nèi)存就沒有這樣的定律,它每次發(fā)展就像擠牙膏一樣,每次擠出一點,所以CPU更新迭代快它的處理速度就很快,而內(nèi)存更新迭代慢所以處理的速度遠遠跟不上CPU處理的速度,且CPU每次從內(nèi)存中拿取數(shù)據(jù),需要通過系統(tǒng)總線拿取數(shù)據(jù),這樣就會導致性能嚴重的降低,為解決CPU與內(nèi)存之間速率不匹配的問題,現(xiàn)代計算機系統(tǒng)中引入了緩存(Cache)用于提高性能,這樣CPU就可以直接讀取緩存中的數(shù)據(jù)。


          以上圖為例,在多核CPU中,每個內(nèi)核都有自己的緩存,這就引來的一個問題,當緩存的數(shù)據(jù)與內(nèi)存中的數(shù)據(jù)發(fā)生不一致的話該怎么辦?于是就引來了緩存一致性協(xié)議啦。


          3
          緩存一致性是什么


          MESI(Modified-Exclusive-Shared-Invalid)協(xié)議是一種廣為使用的緩存一致性協(xié)議,類似讀寫鎖 對于同一地址的讀內(nèi)存操作是并發(fā)的,針對同一地址的寫操作是獨占的,對于內(nèi)存地址寫操作同一時間只能由一個處理器來執(zhí)行。為了保持數(shù)據(jù)的一致性,MESI將緩存條目的狀態(tài)劃分為Modified.Exclusive,Shared,Invalid


          MESI協(xié)議中一個緩存條目的狀態(tài)Flag值分為以下四種

          1. Invalid(無效的,記為I) 相應(yīng)緩存行中不包含任何內(nèi)存地址對應(yīng)的有效副本數(shù)據(jù),是緩存條目的初始狀態(tài)
          2. Shared(共享的,記為S)緩存行中包含相應(yīng)內(nèi)存地址數(shù)據(jù)的副本,其他處理器高速緩存中也可能包含相應(yīng)地址內(nèi)存的副本,緩存行中的數(shù)據(jù)與內(nèi)存的一致
          3. Exclusive(獨占的,記為E)緩存行獨占相應(yīng)內(nèi)存地址數(shù)據(jù)的副本,其他處理器高速緩存不包含相同的副本或者副本失效,緩存行中的數(shù)據(jù)與主內(nèi)存數(shù)據(jù)一致
          4. Modified(更改過,記為M)相應(yīng)緩存行包含更新后的數(shù)據(jù),其他處理器相同tag的緩存行只有唯一的M狀態(tài),與主內(nèi)存的數(shù)據(jù)不一致

          MESI定義了一組message用于協(xié)調(diào)各個處理器的讀寫內(nèi)存操作,處理器在執(zhí)行內(nèi)存的讀寫操作時,在必要的情況下會往bus中發(fā)送特定的請求消息,每個處理器攔截這些消息,在一定情況下往bus回復消息。


          如下圖,就是MESI的概要圖。


          通過上面的理論,還不好解釋MESI協(xié)議在CPU多核中到底是如何運用的,我會在下面通過幾張圖片的案例,來詳細剖析它協(xié)議的轉(zhuǎn)換過程。


          如下案例,在內(nèi)存中存在一個count共享變量,現(xiàn)在 "線程0" 需要用到該變量,那么 "線程0" 會從內(nèi)存中通過bus總線將變量副本拷貝到緩存中,需要注意的是,線程都會對bus總線進行監(jiān)聽,例如 "線程0" 讀取了共享變量,因為 "線程1"對bus總線進行了監(jiān)聽,所以它是知道的 "線程0" 進行了讀取操作。但是目前為止該緩存變量它的狀態(tài)為 "E(獨占)",為什么為獨占?因為該變量只被一個線程所使用。


          接著,"線程1" 也需要用到該共享變量,它同樣也會通過bus總線去內(nèi)存中拷貝變量副本,這時 "線程0" 監(jiān)聽到 "線程1" 也拷貝了共享變量副本,此時 "線程0" 它會將內(nèi)部的變量狀態(tài)標識改為 "S(共享)",而 "線程1" 這邊也會將變量狀態(tài)標識為 "S(共享)" ,那么此時線程就不能夠隨便的對變量進行修改了,因為該變量被多個線程所使用,所以CPU需要同時對兩個線程中的變量進行維護。


          然后接著,"線程1" 對變量了進行修改,此時 "線程1" 會將共享變量的狀態(tài)標識改為 "M(修改)",并通知bus總線該變量已經(jīng)發(fā)生了修改,那么這時候 "線程0" 監(jiān)聽到了 "線程1" 修改了共享變量, "線程0" 就會將變量狀態(tài)標識改為 "I(丟棄)",當CPU識別到 "線程1" 變量狀態(tài)標識為i的時候,就會將該變量從緩存中進行丟棄,重新去內(nèi)存中拷貝最新的變量副本。


          但是此刻會衍生出另外一個問題,假如兩個線程同時進行對變量進行了修改,那么到底是哪個線程修改成功呢?還是說晚修改的變量會對早修改的變量就行覆蓋?那這樣豈不是會造成臟數(shù)據(jù)的發(fā)生?
          針對以上這種情況當然是不允許發(fā)生的啦,如果線程需要對變量進行修改,會先在本地的緩存行中上一個lock鎖(本地寫緩存行),因為數(shù)據(jù)都是存放在緩存行中的,但是會有這么一個問題,它們是對各自的緩存行進行上鎖,其他的線程是并不知道,還是無法解決多個線程同時操作造成臟數(shù)據(jù)的發(fā)生,但是CPU也考慮到緩存一致性的問題,假如多個線程都對各自的緩存行進行了上鎖,也同時發(fā)送本地寫緩存行消息給了bus總線,那么此時就會由bus總線來決定,由某個線程來進行修改。


          以上是針對正常的情況,MESI協(xié)議能夠正常的對緩存行進行狀態(tài)標識轉(zhuǎn)換,那么我們來聊一聊針對非正常情況,MESI協(xié)議是否還適用呢?
          在CPU緩存中,它的緩存大小為64個字節(jié),假如我們現(xiàn)在內(nèi)存中有一個大對象,它的大小為124個字節(jié),那么在CPU中一個緩存行是無法進行存儲的,它會將變量存儲在兩個緩存中,這樣的話CPU在對變量進行操作就不再是原子操作,MESI協(xié)議無法同時對線程內(nèi)的兩個緩存行進行l(wèi)ock加鎖,這時MESI協(xié)議失效,緩存行鎖失效,從而晉升到bus總線鎖。


          總線鎖的概念:將總線鎖住,只有一個內(nèi)核線程能夠操作該變量,其他的線程只能默默的看著它進行操作啦,它的壞處在于,由多核的CPU變成了單核CPU操作效率大幅度的降低。


          不知道大家伙看到這,對CPU底層對多線程數(shù)據(jù)處理,以及它的安全性問題是否有一個比較清晰的認知了呢?關(guān)于CPU底層有很多涉及到硬件層面的內(nèi)容啦,大家伙感興趣可自行查閱相關(guān)文檔哦~


          我是黎明大大,我知道我沒有驚世的才華,也沒有超于凡人的能力,但畢竟我還有一個不屈服,敢于選擇向命運沖鋒的靈魂,和一個就是傷痕累累也要義無反顧走下去的心。


          如果您覺得本文對您有幫助,還請關(guān)注點贊一波,后期將不間斷更新更多技術(shù)文章


          掃描二維碼關(guān)注我
          不定期更新技術(shù)文章哦



          JUC并發(fā)編程之單例模式雙重檢驗鎖陷阱

          JUC并發(fā)編程之Volatile關(guān)鍵字詳解

          JUC并發(fā)編程之JMM內(nèi)存模型詳解

          深入Hotspot源碼與Linux內(nèi)核理解NIO與Epoll

          基于Python爬蟲爬取有道翻譯實現(xiàn)翻譯功能

          JAVA集合之ArrayList源碼分析

          Mysql幾種join連接算法



          發(fā)現(xiàn)“在看”和“贊”了嗎,因為你的點贊,讓我元氣滿滿哦
          瀏覽 99
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产黄色毛片网站 | 国产麻豆黄色有码 | aa无码 | 日本三级小视频 | 午夜黄色直播 |