volatile實現(xiàn)

volatile關鍵字有兩方面的作用,一是保證共享變量可見性,二是禁止指令重排。

一、內(nèi)存可見性

站在一個java程序員的角度,內(nèi)存可見性應該從兩個方面去理解,多核CPU的緩存一致性,以及JMM多線程線程棧本地內(nèi)存與主存一致性。

1.1、CPU緩存一致性

現(xiàn)代CPU多采用多級緩存架構(gòu),


cpu緩存架構(gòu)

緩存大大縮小了高速CPU與低速內(nèi)存之間的差距。以三層緩存架構(gòu)為例:
L1 Cache最接近CPU, 容量最小(如32K、64K等)、速度最高,每個核上都有一個L1 Cache。
L2 Cache容量更大(如256K)、速度更低, 一般情況下,每個核上都有一個獨立的L2 Cache。
L3 Cache最接近內(nèi)存,容量最大(如12MB),速度最低,在同一個CPU插槽之間的核共享一個L3 Cache。
在這種架構(gòu)下,可能會存在下面的問題:
1、Core0與Core1命中了內(nèi)存中的同一個地址,那么各自的L1 Cache會緩存同一份數(shù)據(jù)的副本。
2、最開始,Core0與Core1都在友善的讀取這份數(shù)據(jù)。
3、突然,Core0要使壞了,它修改了這份數(shù)據(jù),因為緩存的存在,這個修改并不會馬上同步到主存,二十僅僅修改了Core 0 自己的L1 Cache中的值,此時Core1如果還繼續(xù)以自己L1 Cache中的數(shù)據(jù)為準,必然導致錯誤的結(jié)果。

如何解決這個問題呢?緩存一致性協(xié)議MESI。
關于緩存一致性協(xié)議,可參考下面這篇博客,寫得非常好。
https://www.cnblogs.com/yanlong300/p/8986041.html
簡單來講,就是當某一核改變了共享變量的值,cpu會發(fā)出一個指令,讓其他核心L1 Cache中保存的值變成失效狀態(tài),當其他核心需要讀取這個值時,需要到主存中重新加載。

1.2、工作內(nèi)存與主存的一致性

Java工作內(nèi)存與主存.png

java每個線程的工作內(nèi)存都會有一個共享變量的備份,若一個線程中的值改變了而未同步到主存,另一個線程可能會讀到臟數(shù)據(jù)。
若共享變量被定義未volatile,則:
寫一個volatile變量時,JMM會把線程對應的工作內(nèi)存中的變量值刷新到主存。
讀一個volatile變量時,JMM會把線程對應的本地內(nèi)存置為無效,然后從主存中讀取該變量。

二、指令重排

指令重排分為編譯器重排與處理器重排,JMM制定了如下的volatile重排序規(guī)則:

是否允許重排序 第二個操作 第二個操作 第二個操作
第一個操作 普通讀/寫 volatile讀 volatile寫
普通讀寫
volatile讀
volatile寫

可以看出:
1、當?shù)诙€操作是volatile寫時,不論第一個操作是什么,都不允許重排。
2、當?shù)谝粋€操作是volatile讀時,不論第二個操作是什么,都不允許重排。
3、當?shù)谝粋€操作是volatile寫,第二個操作是volatile讀時,不允許重排。

Java編譯器通過插入內(nèi)存屏障來實現(xiàn)以上規(guī)則。JMM內(nèi)存屏障分為四種:

屏障類型 指令示例 說明
LoadLoad Barriers Load1; LoadLoad; Load2 確保load1先于load2
StoreStore Barriers Store1; StoreStore; Store2 確保store1先于store2
LoadStore Barriers Load1; LoadStore; Store2 確保load1先于Store2
StoreLoad Barriers Store1; StoreLoad; Load2 確保store1先于load2

采用以下策略進行內(nèi)存屏障插入:

  • 在每個volatile寫操作的前面插入一個StoreStore屏障。
  • 在每個volatile寫操作的后面插入一個StoreLoad屏障。
  • 在每個volatile讀操作的前面插入一個Load Load屏障。
  • 在每個volatile讀操作的后面插入一個LoadStore屏障。

參考
http://www.itdecent.cn/p/64240319ed60
https://www.cnblogs.com/yanlong300/p/8986041.html
《Java并發(fā)編程的藝術》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容