關(guān)鍵字: volatile

參考原文: http://www.importnew.com/18126.html
基本是對原文的精簡, 推薦閱讀原文以獲得詳細(xì)講解.

volatile能夠保證值在修改時會立即更新到主存. 當(dāng)其他線程讀取時讀到的一定是最新的

volatile關(guān)鍵字和java內(nèi)存模型有關(guān), 所以先了解下內(nèi)存模型

簡述:
cpu運(yùn)行速度遠(yuǎn)快于對內(nèi)存的讀寫, 為了加快速度, 增加了高速緩存. 而一旦增加緩存, 就會出現(xiàn)緩存一致性問題.

解決思路:
1. 在總線上加Lock;
2. 通過緩存一致性協(xié)議;

早期使用思路1解決問題, 但是這樣的話其他cpu無法訪問內(nèi)存, 效率低下.
所以出現(xiàn)了緩存一致性協(xié)議, 最出名的就是Intel的MESI協(xié)議.

核心思路:
當(dāng)cpu寫數(shù)據(jù)的時候, 如果發(fā)現(xiàn)操作的變量是共享變量, 即在其他cpu中也存在該變量的副本, 則發(fā)出信號通知其他cpu將該變量的緩存行置為無效狀態(tài). 讓他們重新從內(nèi)存中讀取最新值.

并發(fā)編程常見問題:
1.原子性問題;
2. 可見性問題; 一個線程修改了變量, 其他線程能夠立馬看到修改的值.
3. 有序性問題;

有序性

虛擬機(jī)--指令重排序

//好例子
//線程1:
context = loadContext();   //語句1
inited = true;             //語句2
 
//線程2:
while(!inited ){
  sleep()
}
doSomethingwithconfig(context);

語句1和語句2可能被重排, 導(dǎo)致線程2讀取inited為true. 結(jié)果加載配置的時候卻沒加載到....

指令重排序不會影響單線程的執(zhí)行, 但是會影響線程并發(fā)執(zhí)行的正確性.

java內(nèi)存模型

java內(nèi)存模型規(guī)定所有的變量都存在主存當(dāng)中, 每個線程有自己的工作內(nèi)存, 線程對變量的操作都必須在工作內(nèi)存中進(jìn)行, 而不能直接對主存進(jìn)行操作, 并且每個線程不能訪問其他線程的工作內(nèi)存.

x = 10;         //語句1   **原子性**
y = x;         //語句2     **不是原子性**  包含兩個動作: 1.讀取x的值;  2.寫入工作內(nèi)存;(注意工作內(nèi)存四個字)
x++;           //語句3      **不是原子性**  三步: 讀-改-寫  
x = x + 1;     //語句4     **不是原子性**  三步: 讀-改-寫  

在32位平臺上, 保存64位數(shù)據(jù)會分成兩節(jié). 導(dǎo)致不能保證原子性(現(xiàn)在據(jù)說已經(jīng)實(shí)現(xiàn)原子性了?)...但是不論如何, 加上volatile關(guān)鍵字是良好的編程規(guī)范.

synchronized和lock自然也能保證可見性. 只是性能上沒有volatile更優(yōu). 請因地制宜, 合理使用.

volatile的兩層含義

  1. 保證了不同線程對這個變量操作時的可見性;
  2. 禁止進(jìn)行指令重排序;

"禁止指令重排序"的實(shí)際使用

//線程1:
context = loadContext();   //語句1
volatile inited = true;             //語句2    加上volatile,保證語句2在語句1之后執(zhí)行.
 
//線程2:
while(!inited ){
  sleep()
}

doSomethingwithconfig(context);

volatile保證可見性, 卻無法保證原子性.

使用volatile關(guān)鍵字的兩個條件:

  1. 對變量的寫操作不依賴于當(dāng)前值;
  2. 該變量沒有包含在具有其他變量的不變式中;

下面列舉幾個Java中使用volatile的幾個場景。

1.狀態(tài)標(biāo)記量

volatile boolean flag = false;
while(!flag){
    doSomething();
}
public void setFlag() {
    flag = true;
}
volatile boolean inited = false;
//線程1:
context = loadContext();  
inited = true;            
 
//線程2:
while(!inited ){
sleep()
}
doSomethingwithconfig(context);

2.double check

class Singleton{
    private volatile static Singleton instance = null;
 
    private Singleton() {
 
    }
 
    public static Singleton getInstance() {
        if(instance==null) {
            synchronized (Singleton.class) {
                if(instance==null)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市沟突,隨后出現(xiàn)的幾起案子盆赤,更是在濱河造成了極大的恐慌厌处,老刑警劉巖行瑞,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叹阔,死亡現(xiàn)場離奇詭異截酷,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)饶辙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門蹲诀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人弃揽,你說我怎么就攤上這事脯爪。” “怎么了矿微?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵痕慢,是天一觀的道長。 經(jīng)常有香客問我涌矢,道長掖举,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任娜庇,我火速辦了婚禮塔次,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘名秀。我一直安慰自己励负,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布匕得。 她就那樣靜靜地躺著继榆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪汁掠。 梳的紋絲不亂的頭發(fā)上略吨,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機(jī)與錄音调塌,去河邊找鬼晋南。 笑死,一個胖子當(dāng)著我的面吹牛羔砾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播偶妖,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼姜凄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了趾访?” 一聲冷哼從身側(cè)響起态秧,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎扼鞋,沒想到半個月后申鱼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愤诱,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年捐友,在試婚紗的時候發(fā)現(xiàn)自己被綠了淫半。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡匣砖,死狀恐怖科吭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情猴鲫,我是刑警寧澤对人,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站拂共,受9級特大地震影響牺弄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜宜狐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一猖闪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肌厨,春花似錦培慌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至表鳍,卻和暖如春馅而,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背譬圣。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工瓮恭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人厘熟。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓屯蹦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親绳姨。 傳聞我的和親對象是個殘疾皇子登澜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評論 2 355