CAS和ABA

獨(dú)占鎖(悲觀鎖)與樂(lè)觀鎖

在多線程編程的時(shí)候惋啃,為了保證多個(gè)線程對(duì)一個(gè)對(duì)象可以安全進(jìn)行訪問(wèn)時(shí),我們需要加同步鎖synchronized,保證對(duì)象的在使用時(shí)的正確性,synchronized就是一種獨(dú)占鎖,它會(huì)導(dǎo)致所有需要此鎖的線程掛起,等待鎖的釋放。

加鎖會(huì)導(dǎo)致一下問(wèn)題:

加多線程競(jìng)爭(zhēng)下失驶,加鎖和釋放鎖會(huì)導(dǎo)致較多的上下文切換,引起性能問(wèn)題枣购。
多線程可以導(dǎo)致死鎖的問(wèn)題嬉探。
多線程持有的鎖會(huì)導(dǎo)致其他需要此鎖的線程掛起。

樂(lè)觀鎖(CAS)的思想?yún)s是不加鎖棉圈,那不加鎖如何確保某一變量的操作沒(méi)有被其他線程修改過(guò)涩堤?

這里就需要CAS操作(CompareAndSwap)來(lái)實(shí)現(xiàn)

CAS有三個(gè)操作參數(shù):內(nèi)存地址,期望值分瘾,要修改的新值胎围,當(dāng)期望值和內(nèi)存當(dāng)中的值進(jìn)行比較不相等的時(shí)候,表示內(nèi)存中的值已經(jīng)被別線程改動(dòng)過(guò)芹敌,這時(shí)候失敗返回痊远,只有相等時(shí),才會(huì)將內(nèi)存中的值改為新的值氏捞,并返回成功。

這里我們可以看一下JAVA的原子類AtomicLong.getAndIncrement()的實(shí)現(xiàn)冒版,來(lái)理解一下CAS這一樂(lè)觀鎖(JDK 1.8)

public final long getAndIncrement() {
   return unsafe.getAndAddLong(this, valueOffset, 1L);
}

接著看一下 Unsafe.getAndAddLong()的實(shí)現(xiàn):

public final long getAndAddLong(Object var1, long var2, long var4) {
   long var6;
   do {
       var6 = this.getLongVolatile(var1, var2);
   } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));
   return var6;
}

這里我們可以看到AtomicLong.getAndIncrement()的實(shí)現(xiàn)就是通過(guò)CAS循環(huán)操作的實(shí)現(xiàn)液茎,只有期望值與真實(shí)值相同情況下,CAS操作才會(huì)成功執(zhí)行辞嗡,退出循環(huán)捆等,如果失敗則繼續(xù)自旋,直到成功续室。

具體流程如下


ABA問(wèn)題

ABA問(wèn)題是指在CAS操作時(shí)栋烤,其他線程將變量值A(chǔ)改為了B,但是又被改回了A挺狰,等到本線程使用期望值A(chǔ)與當(dāng)前變量進(jìn)行比較時(shí)明郭,發(fā)現(xiàn)變量A沒(méi)有變买窟,于是CAS就將A值進(jìn)行了交換操作,但是實(shí)際上該值已經(jīng)被其他線程改變過(guò)薯定,這與樂(lè)觀鎖的設(shè)計(jì)思想不符合始绍。ABA問(wèn)題的解決思路是,每次變量更新的時(shí)候把變量的版本號(hào)加1话侄,那么A-B-A就會(huì)變成A1-B2-A3亏推,只要變量被某一線程修改過(guò),改變量對(duì)應(yīng)的版本號(hào)就會(huì)發(fā)生遞增變化年堆,從而解決了ABA問(wèn)題吞杭。在JDK的java.util.concurrent.atomic包中提供了AtomicStampedReference來(lái)解決ABA問(wèn)題,該類的compareAndSet是該類的核心方法变丧,實(shí)現(xiàn)如下:

public boolean compareAndSet(V   expectedReference,
                            V   newReference,
                            int expectedStamp,
                            int newStamp) {
   Pair<V> current = pair;
   return
       expectedReference == current.reference &&
       expectedStamp == current.stamp &&
       ((newReference == current.reference &&
         newStamp == current.stamp) ||
        casPair(current, Pair.of(newReference, newStamp)));
}

我們可以發(fā)現(xiàn)芽狗,該類檢查了當(dāng)前引用與當(dāng)前標(biāo)志是否與預(yù)期相同,如果全部相等锄贷,才會(huì)以原子方式將該引用和該標(biāo)志的值設(shè)為新的更新值译蒂,這樣CAS操作中的比較就不依賴于變量的值了。

具體流程如下


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谊却,一起剝皮案震驚了整個(gè)濱河市柔昼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌炎辨,老刑警劉巖捕透,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異碴萧,居然都是意外死亡乙嘀,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)破喻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)虎谢,“玉大人,你說(shuō)我怎么就攤上這事曹质∮へ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵羽德,是天一觀的道長(zhǎng)几莽。 經(jīng)常有香客問(wèn)我,道長(zhǎng)宅静,這世上最難降的妖魔是什么章蚣? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮姨夹,結(jié)果婚禮上纤垂,老公的妹妹穿的比我還像新娘矾策。我一直安慰自己,他們只是感情好洒忧,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布蝴韭。 她就那樣靜靜地躺著,像睡著了一般熙侍。 火紅的嫁衣襯著肌膚如雪榄鉴。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,950評(píng)論 1 291
  • 那天蛉抓,我揣著相機(jī)與錄音庆尘,去河邊找鬼。 笑死巷送,一個(gè)胖子當(dāng)著我的面吹牛驶忌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播笑跛,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼付魔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了飞蹂?” 一聲冷哼從身側(cè)響起几苍,我...
    開(kāi)封第一講書(shū)人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎陈哑,沒(méi)想到半個(gè)月后妻坝,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惊窖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年刽宪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片界酒。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡圣拄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出毁欣,到底是詐尸還是另有隱情售担,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布署辉,位于F島的核電站,受9級(jí)特大地震影響岩四,放射性物質(zhì)發(fā)生泄漏哭尝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一剖煌、第九天 我趴在偏房一處隱蔽的房頂上張望材鹦。 院中可真熱鬧逝淹,春花似錦、人聲如沸桶唐。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)尤泽。三九已至欣簇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坯约,已是汗流浹背熊咽。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留闹丐,地道東北人横殴。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像卿拴,于是被迫代替她去往敵國(guó)和親衫仑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

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

  • CAS:對(duì)于內(nèi)存中的某一個(gè)值V堕花,提供一個(gè)舊值A(chǔ)和一個(gè)新值B文狱。如果提供的舊值V和A相等就把B寫(xiě)入V。這個(gè)過(guò)程是原子性...
    kennethan閱讀 403評(píng)論 0 0
  • 一航徙、線程狀態(tài)轉(zhuǎn)換新建(New)可運(yùn)行(Runnable)阻塞(Blocking)無(wú)限期等待(Waiting)限期等...
    達(dá)微閱讀 570評(píng)論 1 2
  • 定義 無(wú)鎖編程是指在不使用鎖的情況下如贷,在多線程環(huán)境下實(shí)現(xiàn)多變量的同步。即在沒(méi)有線程阻塞的情況下實(shí)現(xiàn)同步到踏。這樣可以避...
    匆匆歲月閱讀 1,658評(píng)論 0 0
  • 第2章 java并發(fā)機(jī)制的底層實(shí)現(xiàn)原理 Java中所使用的并發(fā)機(jī)制依賴于JVM的實(shí)現(xiàn)和CPU的指令杠袱。 2.1 vo...
    kennethan閱讀 1,410評(píng)論 0 2
  • 如果你想學(xué)好JAVA這門(mén)技術(shù)楣富,也想在IT行業(yè)拿高薪,可以參加我們的訓(xùn)練營(yíng)課程伴榔,選擇最適合自己的課程學(xué)習(xí)纹蝴,技術(shù)大牛親...
    高級(jí)java架構(gòu)師閱讀 228評(píng)論 0 1