【併發】3、MESI

java代碼

  • 一個java類通過javac編譯成字節碼文件後會通過類加載子系統裝載進元空間
  • 在堆中生成Class實例
  • 創建線程
  • 要執行的方法的字節碼會加到虛擬機棧棧幀中,執行
  • 執行引擎(解釋器/JIT)會將字節碼翻譯成彙編指令(硬件原語)

  • 硬件再將彙編指令翻譯成二進制,速度非常快
  • 這個二進制代碼對應的線程被CPU調度後就會被執行
    因爲jvm是klt的,操作系統中會會維護一個線程常量池,其中的每個線程與jvm上的線程一一對應
    在這裏插入圖片描述

volatile底層如何保證可見性

加了volatile
彙編指令LOCK會觸發硬件緩存鎖定機制(總線鎖,緩存一致性協議),使得在鎖定操作期間不會響應總線控制請求。
硬件緩存鎖定機制有兩種:

  • 總線鎖
    早期用總線鎖保證緩存一致,因爲cpu是通過總線訪問內存的,一個核的線程對總線加鎖後只有他能訪問內存 ,其他線程就不能了。也就是說只要使用了總線鎖,我們的cpu就是單核的。
  • 緩存一致性協議
    緩存一致性是一個協議,目前實現的使用最多的就是mesi去保證緩存一致性。
    當一個緩存行裝不下一個數據的時候,這時mesi就會升級成總線鎖。

MESI

四個字母代表在緩存中四種不同的狀態:

  • M
  • E
  • S
  • I

cpu會監聽總線中被lock前綴修飾的變量,爲其分配四種狀態的一種,如果是第一次讀就會給他分配E狀態, 後來又有別的線程讀了這個變量 ,那就會更改每個的狀態爲S

如果兩個線程都要對這個變量修改, 那就各自對自己的緩存行去加鎖,如果加鎖成功則就可以修改,狀態由S->M。加鎖的同時還要向外部發一個本地寫緩存行的信號,這樣其他擁有這個變量的線程就知道已經被別人寫了,這時候狀態由S->I 並被丟棄。
如果兩個線程都在自己內部加鎖成功,都往外發本地寫緩存行的信號了,那總線就會裁決

在這裏插入圖片描述

store buffer

寫到store buffer的原因,因爲寫操作後發本地寫緩存行到其他cpu需要時間,爲了不影響我接下來的操作,就先寫到store buffer,繼續執行後續的,等到另外一個核收到消息並把該變量失效後(失效即放到queue中排隊,等cpu有空就會去這個失效隊列中把這些變量拿掉),併發消息給剛剛發通知的cpu核,這時這個核再從store buffer中把剛剛改的同步到緩存行並寫到主內存,但是同步回主內存的時機不確定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章