并發(fā)編程 — CAS 原理詳解

在JDK1.5引入的 J.U.C包中的原子類以及Lock等都是基于 volatile 關(guān)鍵結(jié)合 CAS 操作實現(xiàn)的愿棋,為了能夠搞明白 原子類以及 Lock鎖的原理首先要了解 volatile 原理以及 CAS原理招盲,上篇文章我們說了volatile關(guān)鍵字,這篇咱們就聊聊 什么是 CAS 操作算谈。

悲觀鎖與樂觀鎖

在說CAS操作之前咱們先說一下什么是悲觀鎖和樂觀鎖涩禀。

悲觀鎖

悲觀鎖就是總是加鎖最壞的情況,所以每次去拿數(shù)據(jù)時都認(rèn)為別人會修改然眼,所以每次操作共享數(shù)據(jù)時都會上鎖艾船,這樣當(dāng)別人需要訪問共享數(shù)據(jù)時,就必須阻塞等待高每,直到它拿到鎖屿岂。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里面就用到了很多這種鎖機(jī)制,比如行鎖鲸匿、表鎖等爷怀,都是在操作之前先加上鎖。在Java中 synchronized 和 ReentrantLock 等都是獨占的带欢,也就是悲觀鎖运授。

悲觀鎖可以理解為就是 “總有刁民想害朕”。

樂觀鎖

樂觀鎖就是總是情況最好的乔煞,每次去拿共享數(shù)據(jù)的時候認(rèn)為別人不會修改吁朦,所以不會上鎖,但是在更新數(shù)據(jù)的時候會判斷一下在此期間別人是否更改了數(shù)據(jù)渡贾。一般可以通過版本號和 CAS算法實現(xiàn)逗宜。樂觀鎖適用于讀多寫少的場景,這樣可以提供吞吐量空骚。

什么是CAS

CAS 即 Compare And Swap (比較與交換)纺讲,是一種有名的無鎖算法。CAS算法主要涉及到三個參數(shù):

  • 主內(nèi)存中存放的的值V囤屹,也就是線程共享的值熬甚。
  • 線程上次從內(nèi)存中讀取的V值 A,線程私有的牺丙,存放在線程棧幀中则涯,或者CPU緩存中的值复局。
  • 需要寫入主內(nèi)存改些V的值B冲簿,線程對A計算后的值。

大致流程如下所示:

image

CAS帶來的三大問題

ABA問題

因為CAS需要在操作值的時候亿昏,檢查值有沒有發(fā)生變化峦剔,如果沒有發(fā)生變化則更新,但是如果一個值原來是A角钩,變成了B吝沫,又變成了A呻澜,那么CAS進(jìn)行檢查的時候發(fā)現(xiàn)它的值沒有發(fā)生變化,但是實際上卻變化了惨险。ABA問題的解決思路就是使用版本號羹幸。在變量前面加上版本號,每次變量更新的時候把版本號加1辫愉,那么A->B->A就會變成1A->2B->3A栅受。從Java 1.5開始,JDK的Atomic包里提供了一個類AtomicStampedReference來解決ABA問題恭朗。這個類的compareAndSet方法的作用是首先檢查當(dāng)前引用是否等于預(yù)期引用屏镊,并且檢查當(dāng)前的標(biāo)志是否等于預(yù)期標(biāo)志,如果全部相等痰腮,則以原子方式將該應(yīng)用和該標(biāo)志的值設(shè)置為給定的更新值而芥。

開銷大的問題

自旋CAS如果長時間不成功,會給CPU帶來非常大的執(zhí)行開銷膀值,如果JVM能支持處理器提供的pause指令棍丐,那么效率會有一定的提升。pause指令有兩個作用:

第一沧踏,它可以延遲流水線執(zhí)行指令(de-pipeline)骄酗,使CPU不會消耗過多的執(zhí)行資源,延遲的時間取決于具體實現(xiàn)的版本悦冀,在一些處理器上延遲時間是零趋翻;

第二,它可以避免在循環(huán)的時候因內(nèi)存順序沖突(Memory Order Violation)而引起CPU流水線被清空盒蟆,從而提高CPU的實行效率踏烙。

只能保證一個共享變量的原子操作

當(dāng)對一個共享變量執(zhí)行操作時,我們可以使用循環(huán)CAS的方式來保證原子操作历等,但是對多個共享變量操作時讨惩,循環(huán)CAS就無法保證操作的原子性,這個時候可以用鎖寒屯。還有一個取巧的辦法荐捻,就是把多個共享變量合并成一個共享變量來操作。比如寡夹,有兩個共享變量i=2,j=a,合并一下ji=2a,然后用CAS來操作ij处面。從Java 1.5開始,JDK提供了AtomicReference類來保證引用對象之前的原子性菩掏,就可以把多個變量放在一個對象里來進(jìn)行CAS操作魂角。

總結(jié)

本篇文章首先介紹了什么是悲觀鎖和樂觀鎖,然后介紹了 CAS 原理智绸,CAS 就是 比較并交換野揪,也就是在寫入時先比較 主內(nèi)存中值是否跟之前讀取的舊值相等,如果相等就更新斯稳,如果不相等就再次讀取計算海铆,循環(huán)往復(fù)。CAS 在提高性能的同時挣惰,也帶來了三大問題游添。明白三大問題能夠更好的使用 CAS操作,以及后續(xù)的 原子操作類通熄。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末唆涝,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子唇辨,更是在濱河造成了極大的恐慌廊酣,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赏枚,死亡現(xiàn)場離奇詭異亡驰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)饿幅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門凡辱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人栗恩,你說我怎么就攤上這事透乾。” “怎么了磕秤?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵乳乌,是天一觀的道長。 經(jīng)常有香客問我市咆,道長汉操,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任蒙兰,我火速辦了婚禮磷瘤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘搜变。我一直安慰自己采缚,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布痹雅。 她就那樣靜靜地躺著仰担,像睡著了一般糊识。 火紅的嫁衣襯著肌膚如雪绩社。 梳的紋絲不亂的頭發(fā)上摔蓝,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機(jī)與錄音愉耙,去河邊找鬼贮尉。 笑死,一個胖子當(dāng)著我的面吹牛朴沿,可吹牛的內(nèi)容都是我干的猜谚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼赌渣,長吁一口氣:“原來是場噩夢啊……” “哼魏铅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起坚芜,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤览芳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鸿竖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沧竟,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年缚忧,在試婚紗的時候發(fā)現(xiàn)自己被綠了悟泵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡闪水,死狀恐怖糕非,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情球榆,我是刑警寧澤峰弹,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站芜果,受9級特大地震影響鞠呈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜右钾,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一蚁吝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧舀射,春花似錦窘茁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至邢羔,卻和暖如春驼抹,著一層夾襖步出監(jiān)牢的瞬間桑孩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工框冀, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留流椒,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓明也,卻偏偏與公主長得像宣虾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子温数,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355

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