揭示volatile背後的奧祕——CPU多級緩存與CPU指令重排

Volatile的做用



Volatile是如何保證內存可見性的?

CPU多級緩存

CPU的運行速度很是快,而對磁盤的讀寫IO速度卻很慢,爲了解決這個問題,有了內存的誕生;java

而CPU的速度與內存的讀寫速度之比仍然有着100 : 1的差距,爲了解決這個問題,CPU又在內存與CPU之間創建了多級別緩存:寄存器、L一、L二、L3三級緩存。緩存

CPU三級緩存.png 併發

CPU緩存一個最小單位是64Byte:通過實踐得出,緩存64Byte是一個較爲合適的單位大小,不會由於緩存過大,而使得讀取速度下降,也不會由於緩存過少,而屢次去讀取數據。app

核心1核心2在操做同一緩存行中的不一樣元素時,即便是操做的不一樣元素不會相互形成影響,可是,同一緩存行數據若被修改,則會經過緩存一致性協議來使其餘CPU與核心中的緩存失效,從而從新去內存中讀取數據,形成程序速度變慢。框架

  • 奇技淫巧:在這種狀況下,經過「補齊」一塊64Byte大小的空間,來使得緩存不會由於一致性問題而重複更新。spa

  • 實際應用場景:線程

    • disruptor併發框架
    • JDK8能夠用註解 @Sun.misc.Contended實現兩個對象或者變量絕對不在同一塊緩存行內。



CPU爲何會指令重排?

咱們的程序運行時,會被編譯器轉化成一條一條CPU可以執行的語句,例以下面的程序:code

int a = 1;
int b = 1;

a = a + b;
a++;
複製代碼

簡單地觀察便可發現,第4行與第5行的語句交換順序執行並不會發生最終結果的不一致。cdn

這爲CPU指令重排提供了重排的可行性!對象

而根本緣由是:CPU運行速度與內存讀取速度不匹配,第4行的語句會讓CPU到內存中尋找b的值,從而使CPU空閒時間過多,而考慮到效率問題,CPU就在這一段讀取內存的空閒時間內,先執行了下一條語句,提升程序運行效率。


不容許重排序狀況:
  • happen-before:六項規則

  • as if serial:單線程執行結果不能被改變

  • DCL(Double Check Lock)單例模式:防止對象未建立完成,就已經被另外一個線程返回了

  • ……


volatile 內存屏障hot spot實現:

lock cpu總線,使CPU緩存中的數據失效,使得其餘CPU暫時中止工做達到防止指令重排序。

相關文章
相關標籤/搜索