Java volatile關(guān)鍵字

volatile.png

內(nèi)存模型概念

高速緩存存在的意義:臨時(shí)變量都存在于內(nèi)存中镰官,當(dāng)CPU執(zhí)行程序時(shí),速度是非陈鸹酰快的泳唠,但是牽扯到和內(nèi)存交互,存取數(shù)據(jù)(耗時(shí))卿操,會(huì)影響程序的執(zhí)行速度警检,因此孙援,必須引入高速緩存害淤。當(dāng)執(zhí)行程序時(shí),會(huì)先從內(nèi)存中讀取值拓售,然后復(fù)制給高速緩存窥摄,之后程序執(zhí)行,并將結(jié)果寫入高速緩存础淤,最后崭放,再將緩存中的值刷新進(jìn)入內(nèi)存哨苛。高速緩存的存在,提高了程序的執(zhí)行速度

引入的問題
多線程程序中币砂,各個(gè)線程都有自己的高速緩存建峭,因此當(dāng)他們讀取內(nèi)存中的同一個(gè)值時(shí)(即共享變量),無法保證讀取進(jìn)緩存和寫入內(nèi)存時(shí)序决摧,即緩存不一致亿蒸,就會(huì)產(chǎn)生錯(cuò)誤

如何解決?

  • 總線加lock
  • 通過緩存一致性協(xié)議掌桩。其中一個(gè)協(xié)議的思想為:當(dāng)一個(gè)線程修改了值并將其寫入內(nèi)存之后边锁,會(huì)通知其他線程,將其他線程中的緩存置為無效狀態(tài)波岛,當(dāng)其他線程需要讀取該值時(shí)茅坛,必須重新從內(nèi)存中讀取

三個(gè)性質(zhì)

  • 原子性
    指一個(gè)或者多個(gè)操作,要么全部執(zhí)行并且執(zhí)行過程中不被任何因素打斷则拷,要么就全部都不執(zhí)行
  • 可見性
    指當(dāng)多個(gè)線程訪問同一個(gè)變量時(shí)贡蓖,一旦其中的一個(gè)線程改變了該變量的值,其他的線程立刻就可以看到修改后的值
    個(gè)人認(rèn)為可以簡(jiǎn)單理解為煌茬,當(dāng)一個(gè)線程修改了值后摩梧,會(huì)立即將該值從高速緩存中寫入內(nèi)存,確保其他線程可以正確的讀取到該值
  • 有序性
    Java程序執(zhí)行時(shí)宣旱,為了提高執(zhí)行效率仅父,會(huì)發(fā)生指令重排。
    具體的說浑吟,就是處理器不會(huì)保證代碼會(huì)嚴(yán)格按照語句的先后順序執(zhí)行笙纤,而是會(huì)保證其代碼的執(zhí)行結(jié)果和嚴(yán)格按照順序執(zhí)行語句的結(jié)果一致。
    例如:

Person p = new Person()
大致會(huì)做三件事:

  1. 給Person的實(shí)例分配內(nèi)存空間
  2. 調(diào)用Person()的構(gòu)造函數(shù)组力,初始化成員字段
  3. 將person對(duì)象指向分配的內(nèi)存空間(此時(shí)省容,person就不是null了)

但是,由于上述亂序的存在燎字,上述過程的2和3順序是無法保證的
當(dāng)在多線程情況下腥椒,執(zhí)行順序是1-3-2時(shí),當(dāng)執(zhí)行完1-3后候衍,切換至線程B笼蛛,此時(shí)得到的p并未完全初始化, 在使用時(shí)就會(huì)有問題蛉鹿,這也是DLC單例在多線程環(huán)境下必須加volatile修飾instance的原因
注意:要讓程序在多線程情況下正確的執(zhí)行滨砍,那就必須同時(shí)滿足上述三個(gè)條件,若其中一個(gè)不滿足,就可能會(huì)導(dǎo)致運(yùn)行結(jié)果不正確


Java的內(nèi)存模型

Java中規(guī)定惋戏,所有的變量都是存在主存中领追,每一個(gè)線程都有自己的工作內(nèi)存(相當(dāng)于高速緩存),在程序執(zhí)行時(shí)响逢,線程對(duì)變量的所有操作都必須在其工作內(nèi)存中

  • 原子性
    Java只會(huì)保證所有的基本類型數(shù)據(jù)绒窑,其簡(jiǎn)單的讀取,賦值操作是原子的舔亭,變量之間的賦值不是原子的
    若要其他類型數(shù)據(jù)或者操作實(shí)現(xiàn)原子性回论,可以使用sychronized和lock關(guān)鍵字實(shí)現(xiàn)
    volatile變量并不能提供原子性
  • 可見性
    Java提供volatile關(guān)鍵字保證可見性(只針對(duì)共享變量而言)
    通過volatile修飾,Java保證對(duì)值的修改會(huì)立刻刷新至主存中分歇,當(dāng)其他線程需要讀取時(shí)(不確定是否一定會(huì)從主存中重新讀瓤亍?)职抡,就會(huì)去讀取新值
    同樣的葬燎,也可使用sychronized和lock關(guān)鍵字實(shí)現(xiàn)
  • 有序性
    可以通過volatile關(guān)鍵字實(shí)現(xiàn)部分有序性
    可以使用sychronized和lock關(guān)鍵字實(shí)現(xiàn)

volatile

如果一個(gè)域聲明為volatile,那么編譯器和虛擬機(jī)就知道該域可能是被另一個(gè)線程并發(fā)更新的
volatile修飾共享變量的意義:

  1. 保證對(duì)該域修改的可見性
  2. 禁止指令進(jìn)行重排缚甩,具體是指:
  • 當(dāng)程序執(zhí)行到volatile變量的讀操作或者寫操作時(shí)谱净,在其前面的操作的更改肯定全部已經(jīng)進(jìn)行,且結(jié)果已經(jīng)對(duì)后面的操作可見擅威;在其后面的操作肯定還沒有進(jìn)行壕探;
  • 在進(jìn)行指令優(yōu)化時(shí),不能將在對(duì)volatile變量訪問的語句放在其后面執(zhí)行郊丛,也不能把volatile變量后面的語句放到其前面執(zhí)行
    簡(jiǎn)單來說李请,就是volatile會(huì)保證volatile之前的語句一定會(huì)在volatile之后的語句之前執(zhí)行,但是并不能保證前面的語句不會(huì)亂序執(zhí)行厉熟,其后的語句不會(huì)亂序執(zhí)行

即是指:

  • 它確保指令重排序時(shí)不會(huì)把其后面的指令排到內(nèi)存屏障之前的位置导盅,也不會(huì)把前面的指令排到內(nèi)存屏障的后面;即在執(zhí)行到內(nèi)存屏障這句指令時(shí)揍瑟,在它前面的操作已經(jīng)全部完成白翻;
  • 它會(huì)強(qiáng)制將對(duì)緩存的修改操作立即寫入主存;
  • 如果是寫操作绢片,它會(huì)導(dǎo)致其他CPU中對(duì)應(yīng)的緩存行無效

使用場(chǎng)景:
由于volatile無法保證原子性滤馍,因此,只有在明確可以確保原子性的情況下底循,可以使用volatile巢株,其效率會(huì)高于sychroniezd關(guān)鍵字,例如DCL單例中使用volatile和sychronized確保正確性
假設(shè)對(duì)于共享變量此叠,除了賦值操作之外不會(huì)再有其他操作纯续,那個(gè)可以將其聲明為volatile


參考:這篇博文 https://www.cnblogs.com/dolphin0520/p/3920373.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市灭袁,隨后出現(xiàn)的幾起案子猬错,更是在濱河造成了極大的恐慌,老刑警劉巖茸歧,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倦炒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡软瞎,警方通過查閱死者的電腦和手機(jī)逢唤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涤浇,“玉大人鳖藕,你說我怎么就攤上這事≈欢В” “怎么了著恩?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蜻展。 經(jīng)常有香客問我喉誊,道長(zhǎng),這世上最難降的妖魔是什么纵顾? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任伍茄,我火速辦了婚禮,結(jié)果婚禮上施逾,老公的妹妹穿的比我還像新娘敷矫。我一直安慰自己,他們只是感情好汉额,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布沪饺。 她就那樣靜靜地躺著,像睡著了一般闷愤。 火紅的嫁衣襯著肌膚如雪整葡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天讥脐,我揣著相機(jī)與錄音遭居,去河邊找鬼。 笑死旬渠,一個(gè)胖子當(dāng)著我的面吹牛俱萍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播告丢,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼枪蘑,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起岳颇,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤照捡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后话侧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體栗精,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年瞻鹏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了悲立。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡新博,死狀恐怖薪夕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赫悄,我是刑警寧澤寥殖,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站涩蜘,受9級(jí)特大地震影響嚼贡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜同诫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一粤策、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧误窖,春花似錦叮盘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至丙唧,卻和暖如春愈魏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背想际。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工培漏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人胡本。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓牌柄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親侧甫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子珊佣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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