java中volatile關鍵字的含義

在java線程并發(fā)處理中铺罢,有一個關鍵字volatile的使用目前存在很大的混淆艇挨,以為使用這個關鍵字,在進行多線程并發(fā)處理的時候就可以萬事大吉韭赘。


Java語言是支持多線程的缩滨,為了解決線程并發(fā)的問題,在語言內部引入了 同步塊 和 volatile 關鍵字機制泉瞻。



synchronized


同步塊大家都比較熟悉脉漏,通過 synchronized 關鍵字來實現(xiàn),所有加上synchronized 和 塊語句袖牙,在多線程訪問的時候侧巨,同一時刻只能有一個線程能夠用


synchronized 修飾的方法 或者 代碼塊。



volatile


用volatile修飾的變量鞭达,線程在每次使用變量的時候司忱,都會讀取變量修改后的最的值。volatile很容易被誤用畴蹭,用來進行原子性操作坦仍。



下面看一個例子,我們實現(xiàn)一個計數(shù)器叨襟,每次線程啟動的時候蹂窖,會調用計數(shù)器inc方法际插,對計數(shù)器進行加一



執(zhí)行環(huán)境——jdk版本:jdk1.6.0_31 ,內存 :3G? cpu:x86 2.4G


public class Counter {

? ? public static int count = 0;

? ? public static void inc() {

? ? ? ? //這里延遲1毫秒,使得結果明顯

? ? ? ? try {

? ? ? ? ? ? Thread.sleep(1);

? ? ? ? } catch (InterruptedException e) {

? ? ? ? }

? ? ? ? count++;

? ? }

? ? public static void main(String[] args) {

? ? ? ? //同時啟動1000個線程导梆,去進行i++計算纱兑,看看實際結果

? ? ? ? for (int i = 0; i < 1000; i++) {

? ? ? ? ? ? new Thread(new Runnable() {

? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? public void run() {

? ? ? ? ? ? ? ? ? ? Counter.inc();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }).start();

? ? ? ? }

? ? ? ? //這里每次運行的值都有可能不同,可能為1000

? ? ? ? System.out.println("運行結果:Counter.count=" + Counter.count);

? ? }

}

運行結果:Counter.count=995


實際運算結果每次可能都不一樣弹囚,本機的結果為:運行結果:Counter.count=995抬驴,可以看出,在多線程的環(huán)境下傀履,Counter.count并沒有期望結果是1000

很多人以為虱朵,這個是多線程并發(fā)問題莉炉,只需要在變量count之前加上volatile就可以避免這個問題,那我們在修改代碼看看碴犬,看看結果是不是符合我們的期望

public class Counter {

? ? public volatile static int count = 0;

? ? public static void inc() {

? ? ? ? //這里延遲1毫秒絮宁,使得結果明顯

? ? ? ? try {

? ? ? ? ? ? Thread.sleep(1);

? ? ? ? } catch (InterruptedException e) {

? ? ? ? }

? ? ? ? count++;

? ? }

? ? public static void main(String[] args) {

? ? ? ? //同時啟動1000個線程,去進行i++計算服协,看看實際結果

? ? ? ? for (int i = 0; i < 1000; i++) {

? ? ? ? ? ? new Thread(new Runnable() {

? ? ? ? ? ? ? ? @Override

? ? ? ? ? ? ? ? public void run() {

? ? ? ? ? ? ? ? ? ? Counter.inc();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }).start();

? ? ? ? }

? ? ? ? //這里每次運行的值都有可能不同,可能為1000

? ? ? ? System.out.println("運行結果:Counter.count=" + Counter.count);

? ? }

}

運行結果:Counter.count=992


運行結果還是沒有我們期望的1000绍昂,下面我們分析一下原因



在 java 垃圾回收整理一文中,描述了jvm運行時刻內存的分配偿荷。其中有一個內存區(qū)域是jvm虛擬機棧窘游,每一個線程運行時都有一個線程棧,


線程棧保存了線程運行時候變量值信息跳纳。當線程訪問某一個對象時候值的時候忍饰,首先通過對象的引用找到對應在堆內存的變量的值,然后把堆內存


變量的具體值load到線程本地內存中寺庄,建立一個變量副本艾蓝,之后線程就不再和對象在堆內存變量值有任何關系,而是直接修改副本變量的值斗塘,


在修改完之后的某一個時刻(線程退出之前)赢织,自動把線程變量副本的值回寫到對象在堆中變量。這樣在堆中的對象的值就產(chǎn)生變化了逛拱。

read and load 從主存復制變量到當前工作內存

use and assign? 執(zhí)行代碼敌厘,改變共享變量值

store and write 用工作內存數(shù)據(jù)刷新主存相關內容


其中use and assign 可以多次出現(xiàn)


但是這一些操作并不是原子性台猴,也就是 在read load之后朽合,如果主內存count變量發(fā)生修改之后,線程工作內存中的值由于已經(jīng)加載饱狂,不會產(chǎn)生對應的變化曹步,所以計算出來的結果會和預期不一樣


對于volatile修飾的變量,jvm虛擬機只是保證從主內存加載到線程工作內存的值是最新的


例如假如線程1休讳,線程2 在進行read,load 操作中讲婚,發(fā)現(xiàn)主內存中count的值都是5,那么都會加載這個最新的值


在線程1堆count進行修改之后俊柔,會write到主內存中筹麸,主內存中的count變量就會變?yōu)?


線程2由于已經(jīng)進行read,load操作,在進行運算之后雏婶,也會更新主內存count的變量值為6


導致兩個線程及時用volatile關鍵字修改之后物赶,還是會存在并發(fā)的情況。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末留晚,一起剝皮案震驚了整個濱河市酵紫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖奖地,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件橄唬,死亡現(xiàn)場離奇詭異,居然都是意外死亡参歹,警方通過查閱死者的電腦和手機仰楚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來犬庇,“玉大人缸血,你說我怎么就攤上這事⌒瞪福” “怎么了捎泻?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長埋哟。 經(jīng)常有香客問我笆豁,道長,這世上最難降的妖魔是什么赤赊? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任闯狱,我火速辦了婚禮,結果婚禮上抛计,老公的妹妹穿的比我還像新娘哄孤。我一直安慰自己,他們只是感情好吹截,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布瘦陈。 她就那樣靜靜地躺著,像睡著了一般波俄。 火紅的嫁衣襯著肌膚如雪晨逝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天懦铺,我揣著相機與錄音捉貌,去河邊找鬼。 笑死冬念,一個胖子當著我的面吹牛趁窃,可吹牛的內容都是我干的。 我是一名探鬼主播急前,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼醒陆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了叔汁?” 一聲冷哼從身側響起统求,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤检碗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后码邻,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體折剃,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年像屋,在試婚紗的時候發(fā)現(xiàn)自己被綠了怕犁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡己莺,死狀恐怖奏甫,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情凌受,我是刑警寧澤阵子,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站胜蛉,受9級特大地震影響挠进,放射性物質發(fā)生泄漏。R本人自食惡果不足惜誊册,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一领突、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧案怯,春花似錦君旦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至悍汛,卻和暖如春捞魁,著一層夾襖步出監(jiān)牢的瞬間至会,已是汗流浹背离咐。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奉件,地道東北人宵蛀。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像县貌,于是被迫代替她去往敵國和親术陶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內容

  • 這幾年不喜歡記錄 總覺得那是在矯情煤痕,也抹殺了可以宣泄的方式梧宫,變得不善表達 誰也沒有預知 我們就這樣...
    yierduer閱讀 269評論 0 1
  • 除了眼前的茍且接谨,還有詩和遠方。
    艸原不愛野馬閱讀 142評論 0 0
  • 放假在即塘匣,好像每個人上班都不在狀態(tài)了脓豪,今天一下班,準點就走忌卤。公司出來的時候發(fā)現(xiàn)天空好藍扫夜,好藍,好藍…驰徊,連拍了超多張...
    Miso來了閱讀 179評論 0 0