通過 JVM (HotSpot) 源碼和匯編理解 Java volatile 實(shí)現(xiàn)原理

了解 volatile 前請先了解 「Java 內(nèi)存模型 (JMM)」是什么

一. volatile 作用是什么

  • 保證變量在多線程之間的可見性

  • 防止重排序

    • 編譯器重排序
    • 指令級重排序
    • 內(nèi)存重排序

二. 多線程之間的內(nèi)存可見性是什么帽撑,如果不保證可見性會怎么樣

如果不保證可見性的話范舀,比如下面這段代碼偷霉, 當(dāng)變量 asscse 被改變?yōu)?1 后颓帝,開啟的 thread 并不會結(jié)束運(yùn)行,因?yàn)?asscse 被拷貝到了線程的工作內(nèi)存中(以 server 模式運(yùn)行)

image.png

三. 通過 JVM 源碼和匯編看怎么保證的多線程間的可見性

1. 準(zhǔn)備工作:

運(yùn)行程序打印匯編代碼的設(shè)置
image.png

2. 字節(jié)碼

帶 volatile 關(guān)鍵詞時腾窝,多了一個 ACC_VOLATILE

image.png

3. JVM 源碼

通過 ACC_VOLATILE 看下 JVM 做了啥, 搜索 hotspot 源碼居砖,看到了兩處 is_volatile

image.png

繼續(xù)搜索is_volatile 做了什么虹脯,我靠這也太多了,160 + 結(jié)果奏候,作為 Java 入道程序員循集,這個 C++ 看著確實(shí)有點(diǎn)拙計,得想點(diǎn)別的辦法蔗草。咒彤。

image.png

4. 反編譯為匯編(不帶 volatile 關(guān)鍵詞)

我想看看反匯編出來的代碼在使用和未使用 volatile 關(guān)鍵詞修飾時的差異


image.png

5. 反編譯為匯編(帶 volatile 關(guān)鍵詞)

可以看出相對于不帶 volatile 關(guān)鍵字是多了一行 lock addl $0x0,(%rsp),開心咒精。镶柱。

image.png

6. JVM 源碼

根據(jù) lock addl 搜索到了兩個結(jié)果,哈哈模叙,看到了 '順序存取' 歇拆,打開 orderAccess.hpp 看一下


image.png

下面這張圖中看到了,一大篇注釋范咨,在是解釋內(nèi)存模型 (JSR-133)和他們處理內(nèi)存模型的方法其中包含 lock addl 對應(yīng)的 fence 和其他函數(shù)故觅,感興趣的可以更具體的閱讀:JDK8 hotspot - orderAccess.hpp 源碼

image.png

找到 orderAccess.hpp 的實(shí)現(xiàn),可以看到 fence 函數(shù)中湖蜕,內(nèi)嵌了匯編逻卖,寫入了 lock addl $0x0,(%rsp)


image.png

6. lock addl $0x0,(%rsp) 是什么

IA32 中對 lock 的說明是

The LOCK # signal is asserted during execution of the instruction following the lock prefix. This signal can be used in a multiprocessor system to ensure exclusive use of shared memory while LOCK # is asserted

LOCK 用于在多處理器中執(zhí)行指令時對共享內(nèi)存的獨(dú)占使用宋列。它的作用是能夠?qū)?dāng)前處理器對應(yīng)緩存的內(nèi)容刷新到內(nèi)存昭抒,并使其他處理器對應(yīng)的緩存失效。另外還提供了有序的指令無法越過這個內(nèi)存屏障的作用炼杖。

正是 lock 實(shí)現(xiàn)了 volatile 的「防止指令重排」「內(nèi)存可見」的特性

五. 參考

查看Java的匯編指令Java 內(nèi)存模型
從 HotSpot 源碼看 Java volatile
就是要你懂 Java 中 volatile 關(guān)鍵字實(shí)現(xiàn)原理
volatile在java server模式和client模式下的不同(主內(nèi)存和工作內(nèi)存)
Java并發(fā)編程 - volatile

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末灭返,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子坤邪,更是在濱河造成了極大的恐慌熙含,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件艇纺,死亡現(xiàn)場離奇詭異怎静,居然都是意外死亡邮弹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進(jìn)店門蚓聘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腌乡,“玉大人,你說我怎么就攤上這事夜牡∮肱Γ” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵塘装,是天一觀的道長急迂。 經(jīng)常有香客問我,道長蹦肴,這世上最難降的妖魔是什么僚碎? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮冗尤,結(jié)果婚禮上听盖,老公的妹妹穿的比我還像新娘。我一直安慰自己裂七,他們只是感情好皆看,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著背零,像睡著了一般腰吟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上徙瓶,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天毛雇,我揣著相機(jī)與錄音,去河邊找鬼侦镇。 笑死灵疮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的壳繁。 我是一名探鬼主播震捣,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼闹炉!你這毒婦竟也來了蒿赢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤渣触,失蹤者是張志新(化名)和其女友劉穎羡棵,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嗅钻,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡皂冰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年店展,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秃流。...
    茶點(diǎn)故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡壁查,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出剔应,到底是詐尸還是另有隱情睡腿,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布峻贮,位于F島的核電站席怪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏纤控。R本人自食惡果不足惜挂捻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望船万。 院中可真熱鬧刻撒,春花似錦、人聲如沸耿导。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舱呻。三九已至醋火,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間箱吕,已是汗流浹背芥驳。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茬高,地道東北人兆旬。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像怎栽,于是被迫代替她去往敵國和親丽猬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容