Java內(nèi)存模型-volatile內(nèi)存語義

章節(jié)目錄

  • 1.volatile 的特性
    • 為什么volatile修飾變量的寫操作不是原子性的?
  • 2.volatile 寫-讀建立的 happens-before 關(guān)系
  • 3.volatile 寫-讀的內(nèi)存語義

1.volatile 的特性

首先應(yīng)該明確的一點是:當(dāng)聲明共享變量為volatile后舷嗡,對這個變量的讀/寫(分為單元素讀寫,與復(fù)合寫操作)屯曹。不同的讀寫模式下,volatile變量對寫操作的原子性體現(xiàn)是不一樣的往核。

理解volatile特性的一個好辦法是把對volatile變量的單個讀/寫晾腔,看成是同一個鎖對這些單個讀/寫操作做了同步,示例代碼如下所示:

class VolatileFeaturesExample {
   volatile long vl = 0L;
   public void set(long l){
      vl = l;
   }

   public void getAndIncrement() {
       vl++;
   }

  public long get(){
     return vl;
  }
}

假設(shè)有多個線程調(diào)用上述程序中的3個方法场绿,這個程序語義和下面的程序語義等價

class VolatileFeaturesExample {
   long vl = 0L;
   public  synchronized void set(long l){
      vl = l;
   }

   public void getAndIncrement() {
       long temp = get();
       temp +=1L;
       set(temp);
   }

  public syntronized long get(){
     return vl;
  }
}

解釋

  • 如這兩個程序所示剖效,一個volatile 變量的單個讀/寫操作,與一個普通變量的讀/寫操作都是使用同一個鎖來同步焰盗,他們之間的執(zhí)行效果相同璧尸。
  • 鎖的happens-before規(guī)則(保證前一個操作結(jié)果對后一個操作立即可見)保證釋放鎖和獲取鎖的兩個線程之間的內(nèi)存可見性。這很好的解釋了對于一個volatile變量的讀熬拒,總能看到任意線程對這個volatile變量最后的寫入爷光。
  • 鎖的語義決定了臨界代碼區(qū)的執(zhí)行具有原子性。這意味著澎粟,即使是64位的long型和double型變量蛀序,只要它是volatile變量,對該變量的單個讀/寫就具有原子性活烙,如果是多個volatile操作徐裸,或這是volatile++這種復(fù)合操作,這些操作在整體上是不具有原子性的啸盏。

volatile 自身特性:

1.內(nèi)存可見性:對一個volatile變量的讀重贺,總能看到任意線程對這個volatile變量
  最后的寫入(內(nèi)存可見性保證)
2.原子性:對任意單個volatile變量的單獨的讀寫操作,都具有原子性回懦。但對于
  volatile++這種復(fù)合操作不具有原子性气笙。

2.volatile 寫-讀建立的 happens-before 關(guān)系

JMM基于共享內(nèi)存模型實現(xiàn)線程之間的通信

從jdk1.5 開始 volatile 變量的寫-讀可以實現(xiàn)線程之間的通信。

volatile & synchronized內(nèi)存語義

從內(nèi)存語義來說怯晕,volatile的寫-讀與鎖的釋放-獲取有相同的內(nèi)存效果:volatile
寫和鎖釋放有相同的內(nèi)存語義潜圃;volatile讀與鎖的獲取有相同的內(nèi)存語義。

下面為volatile變量示例代碼:

class VolatileExample {
    int a = 0;//其實是線程共享變量
    volatile boolean flag = false;

    public  void writer(){
        a = 1;                   //1
        flag = true;             //2
    }

   public void reader(){
       if(flage){                //3
         int i = a;              //4
         ......
      }
   }
}

假設(shè)線程A 執(zhí)行 writer() 方法之后贫贝,線程B 執(zhí)行reader() 方法秉犹。根據(jù)happens-before 規(guī)則,這個過程建立的happens-before規(guī)則可以分為三類:
1.根據(jù)程序次序規(guī)則稚晚,1 happens before 2;3 happens before 4.
2.根據(jù)volatile規(guī)則崇堵,2 happens-before 3
3.根據(jù)happens-before c傳遞性規(guī)則 1 happens-before 4

圖形化形勢如下圖所示:

volatile-寫-讀 happens-before 關(guān)系

A線程在寫一個volatile變量后,B線程讀同一個volatile變量客燕。A線程在寫volatile之前所有的可見共享變量鸳劳,在B線程讀到同一個volatile變量之后,將立即變得對B線程可見也搓。

4. volatile 寫-讀的內(nèi)存語義

** volatile 寫內(nèi)存語義 **

當(dāng)寫一個volatile變量時赏廓,JMM會把該線程對應(yīng)的本地內(nèi)存的變量中的變量值強制刷新到主內(nèi)存涵紊。

volatile 讀的內(nèi)存語義

 當(dāng)讀一個volatile變量時,JMM會把該線程對應(yīng)的本地內(nèi)存置為無效幔摸。線程接下來將從主內(nèi)存中讀取共享變量摸柄。

volatile內(nèi)存語義 總結(jié)

  • 線程A 寫一個volatile 變量,實質(zhì)上是線程A 向接下來讀取這個volatile變量的某個線程發(fā)出了(其對共享變量所做修改的)消息既忆。
  • 線程B 讀一個volatile 變量驱负,實質(zhì)上是線程B 接收了之前某個線程發(fā)出的(在寫這個volatile變量之前對共享變量所做修改)消息。
  • 線程A 寫一個volatile 變量患雇,隨后線程B讀這個volatile變量跃脊。這個過程實質(zhì)上是線程A通過主內(nèi)存向線程B發(fā)送消息。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苛吱,一起剝皮案震驚了整個濱河市酪术,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翠储,老刑警劉巖绘雁,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異援所,居然都是意外死亡咧七,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門任斋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人耻涛,你說我怎么就攤上這事废酷。” “怎么了抹缕?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵澈蟆,是天一觀的道長。 經(jīng)常有香客問我卓研,道長趴俘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任奏赘,我火速辦了婚禮寥闪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘磨淌。我一直安慰自己疲憋,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布梁只。 她就那樣靜靜地躺著缚柳,像睡著了一般埃脏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上秋忙,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天彩掐,我揣著相機與錄音,去河邊找鬼灰追。 笑死堵幽,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的监嗜。 我是一名探鬼主播谐檀,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼裁奇!你這毒婦竟也來了桐猬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤刽肠,失蹤者是張志新(化名)和其女友劉穎溃肪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體音五,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡惫撰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了躺涝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厨钻。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖坚嗜,靈堂內(nèi)的尸體忽然破棺而出夯膀,到底是詐尸還是另有隱情,我是刑警寧澤苍蔬,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布诱建,位于F島的核電站,受9級特大地震影響碟绑,放射性物質(zhì)發(fā)生泄漏俺猿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一格仲、第九天 我趴在偏房一處隱蔽的房頂上張望押袍。 院中可真熱鬧,春花似錦凯肋、人聲如沸伯病。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽午笛。三九已至驶冒,卻和暖如春歧胁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工物独, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留复局,地道東北人碌嘀。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓秃励,卻偏偏與公主長得像,于是被迫代替她去往敵國和親围辙。 傳聞我的和親對象是個殘疾皇子我碟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,554評論 2 349

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

  • Java的并發(fā)采用的是共享內(nèi)存模型(而非消息傳遞模型),線程之間共享程序的公共狀態(tài)姚建,線程之間通過寫-讀內(nèi)存中的公共...
    阿斯蒂芬2閱讀 471評論 0 1
  • 目錄: 1. 指令重排 2. 順序一致性 3. volatile 4. final 1.指令重排 要了解指令重排矫俺,...
    西部小籠包閱讀 742評論 0 1
  • 第2章 java并發(fā)機制的底層實現(xiàn)原理 Java中所使用的并發(fā)機制依賴于JVM的實現(xiàn)和CPU的指令。 2.1 vo...
    kennethan閱讀 1,403評論 0 2
  • 李嫵娟 周口太康 原創(chuàng)分享堅持第3 天 雨一直下掸冤,忙碌的一天結(jié)束了厘托。晚上幾個好朋友來家里玩,大家聊的很開心稿湿,知心...
    李嫵娟閱讀 206評論 2 6
  • 終于還是流淚了铅匹,以為自己會忍住,會沒心沒肺的笑饺藤,會在獨處的時候給自己打氣包斑,說一句“我能行!”涕俗〗⑹迹可是,當(dāng)情緒上來的時...
    real時光閱讀 223評論 0 0