多線(xiàn)程安全中的Volatile和Synchronized關(guān)鍵字

內(nèi)存模型

內(nèi)存模型.png

在Java內(nèi)存模型中三圆,線(xiàn)程工作在自己的工作內(nèi)存啼止,他會(huì)保留主存的變量拷貝。對(duì)于普通變量奸焙,為了保證執(zhí)行效率瞎暑,在工作內(nèi)存中對(duì)變量的改變并不會(huì)立刻刷新到主存中中。

Volatile關(guān)鍵字

volatile的意思是易變的与帆,不需要被優(yōu)化的了赌。當(dāng)一個(gè)變量被加上了這個(gè)關(guān)鍵字,就表示這個(gè)變量不需要被優(yōu)化玄糟、緩存勿她。對(duì)該變量的修改會(huì)被立刻刷新到主存中,而當(dāng)其他線(xiàn)程讀取該變量時(shí)阵翎,也會(huì)去主存中讀取新值逢并。

使用場(chǎng)景

1.修飾線(xiàn)程中斷標(biāo)志位

volatile boolean isCancel;

當(dāng)我們希望通過(guò)標(biāo)志位去結(jié)束一個(gè)正在運(yùn)行的線(xiàn)程,那么應(yīng)該對(duì)該標(biāo)志修飾volatile郭卫。

2.單例模式

public class Singleton {
private volatile static Singleton sInstance;    //保證對(duì)象的可見(jiàn)性
private Singleton() {
}
public static Singleton getsInstance() {
    if (sInstance == null) {     //減少每次創(chuàng)建對(duì)象雙重鎖的開(kāi)銷(xiāo)
        synchronized (Singleton.class) {
            if (sInstance == null) {
                sInstance = new Singleton();
            }
        }
    }
    return sInstance;
}
}

問(wèn):為什么這里的volatile關(guān)鍵字是必要的砍聊?
答:因?yàn)閯?chuàng)建對(duì)象不是一個(gè)原子操作。

禁止指令重排
假設(shè)創(chuàng)建一個(gè)對(duì)象需要3個(gè)步驟:
(1)分配內(nèi)存空間贰军。
(2)初始化對(duì)象玻蝌。
(3)將內(nèi)存空間的地址賦值給對(duì)應(yīng)的引用。
但是由于操作系統(tǒng)可以對(duì)指令進(jìn)行重排序词疼,所以上面的過(guò)程也可能會(huì)變成如下過(guò)程:
(1)分配內(nèi)存空間俯树。
(2)將內(nèi)存空間的地址賦值給對(duì)應(yīng)的引用。
(3)初始化對(duì)象

如果采用后面的流程贰盗,可能導(dǎo)致引用不為null许饿,但是對(duì)象還沒(méi)有初始化出來(lái),其他的線(xiàn)程進(jìn)行非空判斷后舵盈,會(huì)引用這個(gè)對(duì)象陋率,導(dǎo)致錯(cuò)誤球化。

volatile的原理和機(jī)制
下面這段話(huà)摘自《深入理解Java虛擬機(jī)》:

“觀察加入volatile關(guān)鍵字和沒(méi)有加入volatile關(guān)鍵字時(shí)所生成的匯編代碼發(fā)現(xiàn),加入volatile關(guān)鍵字時(shí)翘贮,會(huì)多出一個(gè)lock前綴指令”

lock前綴指令實(shí)際上相當(dāng)于一個(gè)內(nèi)存屏障(也成內(nèi)存柵欄)赊窥,內(nèi)存屏障會(huì)提供3個(gè)功能:

1.它確定指令重新排序時(shí)不會(huì)把其后的指令排在屏障之前爆惧,也不會(huì)把前面的指令排到屏障之后狸页。即執(zhí)行到屏障指令時(shí),其前面的指令已經(jīng)全部執(zhí)行完扯再,且該屏障指令的執(zhí)行結(jié)果對(duì)后面的指令可見(jiàn)芍耘。
2.它會(huì)強(qiáng)制對(duì)緩存的修改操作立刻寫(xiě)入主存
3.如果是讀取操作,它會(huì)導(dǎo)致其他線(xiàn)程中的緩存變量無(wú)效

synchronized關(guān)鍵字

要理解這個(gè)關(guān)鍵字的作用熄阻,就必須明白Java線(xiàn)程安全中的一個(gè)重要概念---原子性斋竞。
在Java中,對(duì)基本數(shù)據(jù)類(lèi)型變量的讀取和賦值操作是原子性的秃殉。
如果要實(shí)現(xiàn)更大范圍的原子性操作坝初,就必須用synchronized和Lock來(lái)實(shí)現(xiàn),他們能夠保證任一時(shí)刻只有一個(gè)線(xiàn)程執(zhí)行該代碼塊钾军,從而保證了原子性鳄袍。

當(dāng)訪問(wèn)臨界資源時(shí),為了避免數(shù)據(jù)不一致吏恭,我們會(huì)采取同步操作拗小,以確保在某一時(shí)刻只有一個(gè)線(xiàn)程在操作資源。

synchronized的用法

  1. 對(duì)象鎖
    修飾對(duì)象方法或者明確指定某一個(gè)對(duì)象

  2. 類(lèi)鎖
    修飾靜態(tài)方法或者鎖定.class

同一把鎖在某一時(shí)刻只能被一個(gè)線(xiàn)程持有樱哼,當(dāng)另一個(gè)線(xiàn)程嘗試著獲取該鎖的時(shí)候哀九,會(huì)陷入阻塞狀態(tài)。JVM維持了一個(gè)等待該鎖的隊(duì)列搅幅,一旦該鎖被某個(gè)線(xiàn)程釋放了阅束,那么這個(gè)等待隊(duì)列中的線(xiàn)程會(huì)重新進(jìn)入Ready(可運(yùn)行)狀態(tài),等待調(diào)度器的下一次分配茄唐,進(jìn)而去獲取需要的鎖围俘。

無(wú)論synchronized關(guān)鍵字加在方法上還是對(duì)象上,如果它作用的對(duì)象是非靜態(tài)的琢融,則它取得的鎖是對(duì)象界牡;如果synchronized作用的對(duì)象是一個(gè)靜態(tài)方法或一個(gè)類(lèi),則它取得的鎖是類(lèi)漾抬,該類(lèi)所有的對(duì)象用同一把鎖宿亡。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市纳令,隨后出現(xiàn)的幾起案子挽荠,更是在濱河造成了極大的恐慌克胳,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件圈匆,死亡現(xiàn)場(chǎng)離奇詭異漠另,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)跃赚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)笆搓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人纬傲,你說(shuō)我怎么就攤上這事满败。” “怎么了叹括?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵算墨,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我汁雷,道長(zhǎng)净嘀,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任侠讯,我火速辦了婚禮挖藏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘继低。我一直安慰自己熬苍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布袁翁。 她就那樣靜靜地躺著柴底,像睡著了一般。 火紅的嫁衣襯著肌膚如雪粱胜。 梳的紋絲不亂的頭發(fā)上柄驻,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音焙压,去河邊找鬼鸿脓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛涯曲,可吹牛的內(nèi)容都是我干的野哭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼幻件,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼拨黔!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起绰沥,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤篱蝇,失蹤者是張志新(化名)和其女友劉穎贺待,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體零截,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡麸塞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涧衙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哪工。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绍撞,靈堂內(nèi)的尸體忽然破棺而出正勒,到底是詐尸還是另有隱情得院,我是刑警寧澤傻铣,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站祥绞,受9級(jí)特大地震影響非洲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蜕径,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一两踏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧兜喻,春花似錦梦染、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至遂铡,卻和暖如春肮疗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扒接。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工伪货, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人钾怔。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓碱呼,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親宗侦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子愚臀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

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