java并發(fā) volatile關(guān)鍵字的理解

在多線程的環(huán)境,當(dāng)一個(gè)線程修改了共享變量颗品,另一個(gè)線程能讀取到這個(gè)變量的修改值饮睬,變量java 提供了volatile保證了變量的可見(jiàn)性现恼,輕量級(jí)的synchronized
它實(shí)現(xiàn)的原理主要有以下兩個(gè)方面

  • 追加的LOCK#指令會(huì)使處理器緩存行寫回到內(nèi)存
  • 一個(gè)處理器的緩存寫回到內(nèi)存會(huì)使其他處理器的緩存無(wú)效

volatile的應(yīng)用

先看一段代碼凛澎,假如線程1先執(zhí)行,線程2后執(zhí)行:

//線程1
boolean stop = false;
while(!stop){
    doSomething();
    }
     
  //線程2
  stop = true;

這段代碼是很典型的一段代碼适掰,很多人在中斷線程時(shí)可能都會(huì)采用這種標(biāo)記辦法颂碧。但是事實(shí)上,這段代碼會(huì)完全運(yùn)行正確么类浪?即一定會(huì)將線程中斷么载城?不一定,也許在大多數(shù)時(shí)候戚宦,這個(gè)代碼能夠把線程中斷个曙,但是也有可能會(huì)導(dǎo)致無(wú)法中斷線程(雖然這個(gè)可能性很小锈嫩,但是只要一旦發(fā)生這種情況就會(huì)造成死循環(huán)了)受楼。
下面解釋一下這段代碼為何有可能導(dǎo)致無(wú)法中斷線程。在前面已經(jīng)解釋過(guò)呼寸,每個(gè)線程在運(yùn)行過(guò)程中都有自己的工作內(nèi)存艳汽,那么線程1在運(yùn)行的時(shí)候,會(huì)將stop變量的值拷貝一份放在自己的工作內(nèi)存當(dāng)中对雪。
那么當(dāng)線程2更改了stop變量的值之后河狐,但是還沒(méi)來(lái)得及寫入主存當(dāng)中,線程2轉(zhuǎn)去做其他事情了,那么線程1由于不知道線程2對(duì)stop變量的更改馋艺,因此還會(huì)一直循環(huán)下去栅干。
但是用volatile修飾之后就變得不一樣了:

  • 使用volatile關(guān)鍵字會(huì)強(qiáng)制將修改的值立即寫入主存;
  • 使用volatile關(guān)鍵字的話捐祠,當(dāng)線程2進(jìn)行修改時(shí)碱鳞,會(huì)導(dǎo)致線程1的工作內(nèi)存中緩存變量stop的緩存行無(wú)效(反映到硬件層的話,就是CPU的L1或者L2緩存中對(duì)應(yīng)的緩存行無(wú)效)踱蛀;
  • 由于線程1的工作內(nèi)存中緩存變量stop的緩存行無(wú)效窿给,所以線程1再次讀取變量stop的值時(shí)會(huì)去主存讀取。
    那么在線程2修改stop值時(shí)(當(dāng)然這里包括2個(gè)操作率拒,修改線程2工作內(nèi)存中的值崩泡,然后將修改后的值寫入內(nèi)存),會(huì)使得線程1的工作內(nèi)存中緩存變量stop的緩存行無(wú)效猬膨,然后線程1讀取時(shí)角撞,發(fā)現(xiàn)自己的緩存行無(wú)效,它會(huì)等待緩存行對(duì)應(yīng)的主存地址被更新之后寥掐,然后去對(duì)應(yīng)的主存讀取最新的值靴寂。
    那么線程1讀取到的就是最新的正確的值

注意

volatitle保證了共享變量的可見(jiàn)性,但是并沒(méi)有保證原子性召耘,如果變量額的操作非原子性的百炬,也會(huì)線程不安全。

public class Test {
    public volatile int inc = 0;
     
    public void increase() {
    inc++;
    }
              
    public static void main(String[] args) {
    final Test test = new Test();
    for(int i=0;i<10;i++){
        new Thread(){
            public void run(){
                for(int j=0;j<1000;j++)
                    test.increase();
                    };
                }.start();
            }
                                                                             
    while(Thread.activeCount()>1)  //保證前面的線程都執(zhí)行完    
    Thread.yield();
    System.out.println(test.inc);
    }
}

由于自增操作是非原子操作污它,某一時(shí)刻剖踊,存在兩個(gè)線程讀取同一個(gè)有效的inc 此時(shí)由于是非原子操作,此時(shí)將進(jìn)行兩次++ 但是導(dǎo)致只發(fā)生了一次++操作衫贬。

所以volatile保證了變量的可見(jiàn)性但是不能不能保證線程安全

Java Current包下的原子類通過(guò)CAS(Compare and set)完成同步鎖的一種樂(lè)觀鎖(更新時(shí)判斷是否被修改) 來(lái)保證對(duì)變量的原子操作從而保證了線程安全德澈。
如下面代碼:

private volatile int value;

public final int get() {
        return value;
}
public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return next;
        }
}

?著作權(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)離奇詭異,居然都是意外死亡贴捡,警方通過(guò)查閱死者的電腦和手機(jī)忽肛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)烂斋,“玉大人屹逛,你說(shuō)我怎么就攤上這事础废。” “怎么了罕模?”我有些...
    開(kāi)封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵评腺,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我淑掌,道長(zhǎng)歇僧,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任锋拖,我火速辦了婚禮诈悍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘兽埃。我一直安慰自己侥钳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布柄错。 她就那樣靜靜地躺著舷夺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪售貌。 梳的紋絲不亂的頭發(fā)上给猾,一...
    開(kāi)封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音颂跨,去河邊找鬼敢伸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛恒削,可吹牛的內(nèi)容都是我干的池颈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼钓丰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼躯砰!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起携丁,我...
    開(kāi)封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤琢歇,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(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
  • 文/蒙蒙 一汁掠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧集币,春花似錦考阱、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至当娱,卻和暖如春吃既,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背跨细。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工鹦倚, 沒(méi)想到剛下飛機(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)容

  • 轉(zhuǎn)自:http://www.cnblogs.com/dolphin0520/p/3920373.html vola...
    王帥199207閱讀 458評(píng)論 0 0
  • volatile 關(guān)鍵字解析 原文出處: 海子volatile 這個(gè)關(guān)鍵字可能很多朋友都聽(tīng)說(shuō)過(guò),或許也都用過(guò)溃槐。在 ...
    常青大俠閱讀 589評(píng)論 0 4
  • 對(duì)我而言匣砖,九塊錢算是一個(gè)很容易讓我抓狂的人了。九塊錢是高中的一個(gè)屌絲男同學(xué)昏滴。一副完全不靠譜的臉猴鲫,準(zhǔn)確的說(shuō),他喜歡嬉...
    黑騎士_路西法_丸子閱讀 391評(píng)論 0 0
  • 數(shù)據(jù)流是vue2.0新增的插件vuex的一個(gè)對(duì)象store谣殊,用來(lái)存儲(chǔ)全局的變量及方法,例如:公共的方法和公共組...
    剁剁爺閱讀 818評(píng)論 0 0
  • 初中英語(yǔ)課堂實(shí)例 —— 如何上好一節(jié)英語(yǔ)課 英語(yǔ)新課標(biāo)要求教學(xué)過(guò)程中始終要體現(xiàn)學(xué)生的主體地位拂共,教師要充分發(fā)揮學(xué)生在...
    健康飛翔閱讀 256評(píng)論 0 0