volatile的幾個靈魂拷問

要想講清楚volatile關(guān)鍵字,這時候就應(yīng)該主動從內(nèi)存模型開始講起,然后說原子性宴咧、可見性、有序性的理解径缅,鋪墊好這些才是到volatile關(guān)鍵字的原理掺栅,假定前面一篇內(nèi)存模型的文章已經(jīng)理解到位了,那么這里直接從volatile的原理開搞纳猪!

首先說結(jié)論氧卧,volatile關(guān)鍵字作用的是保證可見性和有序性,并不保證原子性氏堤。只有synchronized關(guān)鍵字同時保證上述三種特性沙绝。但是volatile是輕量級的synchronized,它在多線程中保證了變量的“可見性”鼠锈∩撩剩可見性的意思是當(dāng)一個線程修改了一個變量的值后,另外的線程能夠讀取到這個變量修改后的值购笆。

1粗悯、保證可見性

用 volatile 關(guān)鍵字修飾的共享變量,編譯成字節(jié)碼后增加 Lock 前綴指令同欠,該指令要做兩件事:

  • 將當(dāng)前工作內(nèi)存緩存行的數(shù)據(jù)立即寫回到主內(nèi)存为黎。
  • 寫回主內(nèi)存的操作會使其他工作內(nèi)存里緩存了該共享變量地址的數(shù)據(jù)無效(緩存一致性協(xié)議保證的操作)。

對volatile修飾的變量行您,執(zhí)行寫操作的話铭乾,JVM會發(fā)送一條lock前綴指令給CPU,CPU在計算完之后會立即將這個值寫回主內(nèi)存娃循,同時因為有MESI緩存一致性協(xié)議炕檩,所以各個CPU都會對總線進行嗅探,自己本地緩存中的數(shù)據(jù)是否被別人修改捌斧。

如果發(fā)現(xiàn)別人修改了某個緩存的數(shù)據(jù)笛质,那么CPU就會將自己本地緩存的數(shù)據(jù)過期掉,然后這個CPU上執(zhí)行的線程在讀取那個變量的時候捞蚂,就會從主內(nèi)存重新加載最新的數(shù)據(jù)了妇押。

所以,volatile的可見性就是:lock前綴指令 + MESI緩存一致性協(xié)議

Java程序打印成匯編語句,引用自 https://zhuanlan.zhihu.com/p/77085695

2姓迅、保證有序性

Lock 前綴指令有內(nèi)存屏障的作用葡公。上一篇文章已經(jīng)提到過了蒲祈,JMM一共有4種內(nèi)存屏障纵竖,分別是 LoadLoad、LoadStore柴我、StoreStore、StoreLoad扩然。JMM 給volatile插入內(nèi)存屏障保守策略:

  • 在每個 volatile 寫操作的前面插入一個 StoreStore 屏障艘儒,后面插入一個 StoreLoad 屏障。
  • 在每個 volatile 讀操作的后面插入一個 LoadLoad 屏障和一個 LoadStore 屏障夫偶。
linux系統(tǒng)下x86架構(gòu)的實現(xiàn)

StoreStore屏障可以保證在volatile寫之前界睁,前面所有的普通讀寫操作同步到主內(nèi)存中
StoreLoad屏障可以保證防止前面的volatile寫和后面有可能出現(xiàn)的volatile度/寫進行重排序
LoadLoad屏障可以保證防止下面的普通讀操作和上面的volatile讀進行重排序
LoadStore屏障可以保存防止下面的普通寫操作和上面的volatile讀進行重排序

3、不具備原子性

volatile不具備原子性兵拢,多個線程去寫同一個公共volatile修飾的變量會出現(xiàn)線程安全問題翻斟,對于64位的long和double,如果沒有被volatile修飾卵佛,那么對其操作可以不是原子的杨赤。在操作的時候,可以分成兩步截汪,每次對32位操作疾牲。如果使用volatile修飾long和double,那么其讀寫都是原子操作衙解,這里可以稍稍注意下阳柔。

由于volatile不具備原子性,因此還需要有一個原子性能力的補充蚓峦,這里就可以看看這個文章進行回顧下:《CAS是什么舌剂?Atomic包知多少?》

4暑椰、和Synchronized的內(nèi)存屏障差別

按照可見性保障來劃分霍转。內(nèi)存屏障可分為加載屏障(Load Barrier)和存儲屏障(Store Barrier)。加載屏障的作用是刷新處理器緩存一汽,存儲屏障的作用沖刷處理器緩存避消。Java虛擬機會在 MonitorExit ( 釋放鎖 ) 對應(yīng)的機器碼指令之后插入一個存儲屏障,這就保障了寫線程在釋放鎖之前在臨界區(qū)中對共享變量所做的更新對讀線程的執(zhí)行處理器來說是可同步的召夹。相應(yīng)地岩喷,Java 虛擬機會在 MonitorEnter ( 申請鎖 ) 對應(yīng)的機器碼指令之后臨界區(qū)開始之前的地方插入一個加載屏障,這使得讀線程的執(zhí)行處理器能夠?qū)懢€程對相應(yīng)共享變量所做的更新從其他處理器同步到該處理器的高速緩存中监憎。因此纱意,可見性的保障是通過寫線程和讀線程成對地使用存儲屏障和加載屏障實現(xiàn)的。

按照有序性保障來劃分鲸阔,內(nèi)存屏障可以分為獲取屏障(Acquire Barrier)和釋放屏障 ( Release Barrier )偷霉。獲 取 屏 障 的 使 用 方 式 是 在 一 個 讀 操 作 ( 包括 Read-Modify-Write 以及普通的讀操作 )之后插入該內(nèi)存屏障迄委,其作用是禁止該讀操作與其后的任何讀寫操作之間進行重排序,這相當(dāng)于在進行后續(xù)操作之前先要獲得相應(yīng)共享數(shù)據(jù)的所有權(quán) ( 這也是該屏障的名稱來源 )腾它。釋放屏障的使用方式是在一個寫操作之前插入該內(nèi)存屏障跑筝,其作用是禁止該寫操作與其前面的任何讀寫操作之間進行重排序死讹。這相當(dāng)于在對相應(yīng)共享數(shù)據(jù)操作結(jié)束后釋放所有權(quán)( 這也是該屏障的名稱來源 )瞒滴。 Java虛擬機會在 MonitorEnter( 它包含了讀操作 ) 對應(yīng)的機器碼指令之后臨界區(qū)開始之前的地方插入一個獲取屏障,并在臨界區(qū)結(jié)束之后 MonitorExit ( 它包含了寫操作 ) 對應(yīng)的機器碼指令之前的地方插入一個釋放屏障赞警。因此妓忍,這兩種屏障就像是三明治的兩層面包片把火腿夾住一樣把臨界區(qū)中的代碼(指令序列)包括起來:

可以發(fā)現(xiàn),與volatile類似愧旦,synchronized底層也是通過釋放屏障和獲取屏障的配對使用保障有序性世剖,加載屏障和存儲屏障的配對使用保障可見性。最后又通過鎖的排他性保障了原子性笤虫。

參考文獻

1旁瘫、volatile底層原理詳解
2、synchronized 實現(xiàn)原理與內(nèi)存屏障

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末琼蚯,一起剝皮案震驚了整個濱河市酬凳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌遭庶,老刑警劉巖宁仔,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異峦睡,居然都是意外死亡翎苫,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門榨了,熙熙樓的掌柜王于貴愁眉苦臉地迎上來煎谍,“玉大人,你說我怎么就攤上這事龙屉∧耪常” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵叔扼,是天一觀的道長事哭。 經(jīng)常有香客問我,道長瓜富,這世上最難降的妖魔是什么鳍咱? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮与柑,結(jié)果婚禮上谤辜,老公的妹妹穿的比我還像新娘蓄坏。我一直安慰自己,他們只是感情好丑念,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布涡戳。 她就那樣靜靜地躺著,像睡著了一般脯倚。 火紅的嫁衣襯著肌膚如雪渔彰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天推正,我揣著相機與錄音恍涂,去河邊找鬼。 笑死植榕,一個胖子當(dāng)著我的面吹牛再沧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播尊残,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼炒瘸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了寝衫?” 一聲冷哼從身側(cè)響起顷扩,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎竞端,沒想到半個月后屎即,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡事富,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年技俐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片统台。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡雕擂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贱勃,到底是詐尸還是另有隱情井赌,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布贵扰,位于F島的核電站仇穗,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏戚绕。R本人自食惡果不足惜纹坐,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望舞丛。 院中可真熱鬧耘子,春花似錦果漾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捍歪,卻和暖如春户辱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背费封。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工焕妙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蒋伦,地道東北人弓摘。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像痕届,于是被迫代替她去往敵國和親韧献。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345