volatile

目標(biāo)

1、volatile如何保證內(nèi)存可見性
2绩卤、volatile如何禁止指令重排序
3叁鉴、內(nèi)存屏障
4土涝、內(nèi)存可見性
5、關(guān)于volatile的單例模式

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

1.1 緩存一致性問題

??1但壮、現(xiàn)代計算機(jī)系統(tǒng)在存儲設(shè)備與處理器之間加了一層讀寫速度盡可能解決處理器運算速度的高速緩存來作為內(nèi)存與處理器之間的緩沖: 將運算需要使用到的數(shù)據(jù)復(fù)制到緩存中, 讓運算能快速進(jìn)行, 當(dāng)運算結(jié)束后再從緩存同步回內(nèi)存之中, 這樣處理器就無須等待緩慢的內(nèi)存讀寫.
??2、緩存一致性問題:在多處理器系統(tǒng)中, 每個處理器都有自己的高速緩存, 而它們又共享同一主內(nèi)存, 當(dāng)多個處理器的運算任務(wù)都涉及到同一個塊主內(nèi)存區(qū)域時, 將可能導(dǎo)致各自的緩存數(shù)據(jù)不一致.

1.2 內(nèi)存模型

在特定的操作協(xié)議下, 對特定的內(nèi)存或高速緩存進(jìn)行讀寫訪問的過程抽象.

1.3 內(nèi)存可見性

??1常侣、一個CPU核心對數(shù)據(jù)的修改, 對其他CPU核心立即可見.
??2蜡饵、CPU修改數(shù)據(jù), 首先是對緩存的修改, 然后再同步回主存, 在同步回主存的時候, 如果其他CPU也緩存了這個數(shù)據(jù), 就會導(dǎo)致其他CPU緩存上的數(shù)據(jù)失效, 這樣當(dāng)其他CPU再去它的緩存讀取這個數(shù)據(jù)的時候, 就必須從主存重新獲取.
??3、實現(xiàn)原理一般是基于CPU的MESI協(xié)議, 其中E表示獨占Exclusive, S表示Shared, M表示Modify, I表示Invalid, 如果一個CPU核心修改了數(shù)據(jù), 那么這個CPU核心的數(shù)據(jù)狀態(tài)就會更新為M, 同時其他核心上的數(shù)據(jù)狀態(tài)更新為I, 這個是通過CPU多核之間的嗅探機(jī)制實現(xiàn)的.

1.4 MESI(緩存一致性)

Modify胳施、Exclusive溯祸、Shared、Invalid, 當(dāng)CPU寫數(shù)據(jù)時, 如果發(fā)現(xiàn)操作的變量是共享變量, 即在其他CPU中也存在該變量的副本, 會發(fā)出信號通知其他CPU將該變量的緩存行為置為無效狀態(tài), 因此當(dāng)其他CPU需要讀取這個變量時, 發(fā)現(xiàn)自己緩存中緩存的該變量的緩存行是無效的, 那么它就會從內(nèi)存中重新讀取.

1.5 嗅探機(jī)制

1舞肆、例如在x86處理器下, 將volatile變量修飾的共享變量的Java代碼轉(zhuǎn)換成匯編代碼, 發(fā)現(xiàn)會多了lock修飾.
2焦辅、Lock前綴的指令在多核處理器下會引發(fā)以下事情.
3、將當(dāng)前處理器緩存行的數(shù)據(jù)寫回到系統(tǒng)內(nèi)存
4椿胯、這個寫回內(nèi)存的操作將會使其它CPU里緩存了該內(nèi)存地址的數(shù)據(jù)無效.
5筷登、原理分析:為了提高處理速度, 處理器不直接和內(nèi)存進(jìn)行通信, 而是先將系統(tǒng)內(nèi)存的數(shù)據(jù)讀到內(nèi)部緩存(L1, L2或其它)后再進(jìn)行操作, 但操作完就不知道何時會寫到內(nèi)存. 如果對聲明了volatile的變量進(jìn)行寫操作, JVM會向處理器發(fā)送一條lock前綴的指令. 將這個變量所在的緩存行的數(shù)據(jù)寫回到系統(tǒng)內(nèi)存. 在多處理器下, 為了保證各個處理器緩存是一致的, 就會實現(xiàn)緩存一致性協(xié)議, 每個處理器通過嗅探在總線上傳播的數(shù)據(jù)來檢查自己的緩存的值是否過期, 當(dāng)處理器發(fā)現(xiàn)自己緩存行對應(yīng)的內(nèi)存地址被修改, 就會將當(dāng)前處理器緩存行設(shè)置成無效狀態(tài), 當(dāng)處理器對這個數(shù)據(jù)進(jìn)行修改操作的時候, 會重新匆匆系統(tǒng)內(nèi)存中把數(shù)據(jù)讀到處理器緩存里.

1.6 volatile兩條實現(xiàn)原則

1、Lock前綴指令會引起處理器緩存回寫到內(nèi)存:
??Lock前綴指令導(dǎo)致在執(zhí)行指令期間, 聲言處理器的#LOCK信號. 在多處理器環(huán)境中, LOCK#信號確保在聲言該信號期間, 處理器可以獨占任何共享內(nèi)存. 但是在最近的處理器里, LOCK#信號一般不鎖總線, 而是鎖緩存, 畢竟鎖總線的開銷比較大. 對于Intel486和Pentium處理器, 在鎖操作時, 總是在總線上聲言LOCK#信號. 但在P6和目前的處理器中, 如果訪問的內(nèi)存區(qū)域已經(jīng)緩存在處理器內(nèi)部, 則不會聲言LOCK#信號. 相反, 它會鎖定這塊內(nèi)存區(qū)域的緩存并回寫到內(nèi)存, 并使用緩存一致性機(jī)制來確保修改的原子性, 此操作被稱為"緩存鎖定", 緩存一致性機(jī)制會阻止同時修改由兩個以上處理器緩存的內(nèi)存區(qū)域數(shù)據(jù).
2压状、一個處理器的緩存回寫到內(nèi)存會導(dǎo)致其它的緩存無效:
??IA-32處理器和Intel64處理器使用MESI控制協(xié)議去維護(hù)內(nèi)部緩存和其他處理器緩存的一致性. 在多核處理器系統(tǒng)中進(jìn)行操作的時候, IA-32和Intel 64處理器能嗅探其他處理器訪問系統(tǒng)內(nèi)存和它們的內(nèi)部緩存, 處理器使用嗅探技術(shù)保證它的內(nèi)部緩存仆抵、系統(tǒng)內(nèi)存和其他處理器的緩存的數(shù)據(jù)在總線上保持一致. 通過嗅探一個處理器來檢測其他處理器打算寫內(nèi)存地址, 而這個地址當(dāng)前處于共享狀態(tài), 那么正在嗅探的處理器將使它的緩存行無效, 在下次訪問相同內(nèi)存地址時, 強(qiáng)制執(zhí)行緩存行填充.

1.7 Volatile與原子性的關(guān)系

Volatile限定的是從緩存讀取時刻的校驗.

1.8 原子性
1.9 volatile單例模式
public class Instance {
    private static volatile Instance instance;
    private Instance() {}
    public static Instance getInstance() {
        if (instance == null) {
            instance = new Instance();
        }
    }
}

上面代碼分成三步原子指令:
1跟继、new指令申請內(nèi)存;
2、在申請的內(nèi)存中進(jìn)行Instance的初始化;
3镣丑、將申請的內(nèi)存地址的引用賦值給instance變量;
雖然volatile可以禁止指令重排序, 讓上面三個指令有序執(zhí)行, 但是問題是volatile并不能保證原子性, 所以上面代碼中可能出現(xiàn)的問題是當(dāng)Thread-A執(zhí)行到第二步進(jìn)行new Instance初始化時, 此時還沒有將地址值賦給instance變量, 所以Thread-B此時看到的instance==null再次進(jìn)入if中執(zhí)行new Instance()操作.
所以假設(shè)上面代碼被兩個線程執(zhí)行, new Instance()會執(zhí)行兩次

參考文章:
https://blog.csdn.net/lsunwing/article/details/83154208
http://www.pianshen.com/article/7227186495/
https://blog.csdn.net/weixin_38623001/article/details/79167596

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末舔糖,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子莺匠,更是在濱河造成了極大的恐慌金吗,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件趣竣,死亡現(xiàn)場離奇詭異摇庙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)遥缕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門卫袒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人单匣,你說我怎么就攤上這事夕凝。” “怎么了户秤?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵码秉,是天一觀的道長。 經(jīng)常有香客問我鸡号,道長转砖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任鲸伴,我火速辦了婚禮府蔗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘汞窗。我一直安慰自己礁竞,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布杉辙。 她就那樣靜靜地躺著,像睡著了一般捶朵。 火紅的嫁衣襯著肌膚如雪蜘矢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天综看,我揣著相機(jī)與錄音品腹,去河邊找鬼。 笑死红碑,一個胖子當(dāng)著我的面吹牛舞吭,可吹牛的內(nèi)容都是我干的泡垃。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼羡鸥,長吁一口氣:“原來是場噩夢啊……” “哼蔑穴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起惧浴,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤存和,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后衷旅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捐腿,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年柿顶,在試婚紗的時候發(fā)現(xiàn)自己被綠了茄袖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡嘁锯,死狀恐怖宪祥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情猪钮,我是刑警寧澤品山,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站烤低,受9級特大地震影響肘交,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扑馁,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一涯呻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧腻要,春花似錦复罐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至趟济,卻和暖如春乱投,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背顷编。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工戚炫, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人媳纬。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓双肤,卻偏偏與公主長得像施掏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子茅糜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,543評論 2 349