18.CAS算法

1) 什么是CAS

  1. 應(yīng)用在并發(fā)編程領(lǐng)域
  2. CAS有3個操作數(shù):內(nèi)存值V寞埠,預(yù)期值A(chǔ)阔馋,要修改的值B,當(dāng)且僅當(dāng)預(yù)期值A(chǔ)和內(nèi)存值V相同時钟哥,才將內(nèi)存值修改為B创肥,否則什么都不做达舒。最后返回現(xiàn)在的V作為新一輪預(yù)期值A(chǔ)值朋。
  3. 核心原理是compare and swap: 一個CPU操作指令,不可分割巩搏,具有原子性

2. 適用場景

  1. 樂觀鎖
  2. 并發(fā)容器
  3. 原子類

3) 以AtomicInteger為例昨登,分析在Java中是如何利用CAS實現(xiàn)原子操作的?

  1. 以AtomicInteger的getAndAdd方法為突破口贯底,分析該類是如何通過CAS實現(xiàn)并發(fā)下的累加操作丰辣。
public final int getAndAdd(int delta) {
    return unsafe.getAndAddInt(this, valueOffset, delta);
}
  1. 這里用到了Unsafe類,Unsafe是CAS的核心類禽捆。Java無法直接訪問底層操作系統(tǒng)笙什,而是通過本地native方法類訪問。不過盡管如此胚想,JVM還是開了一個后門琐凭,JDK中有一個Unsafe,提供了硬件級別的原子操作浊服。
  2. AtomicInteger加載Unsafe工具统屈,用來直接操作內(nèi)存數(shù)據(jù)
    • Unsafe來實現(xiàn)底層操作,Unsafe根據(jù)內(nèi)存偏移地址獲取數(shù)據(jù)的原始值。
    • 用volatile修飾value字段臼闻,保證可見性
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;

// 類加載時鸿吆,獲取value的內(nèi)存地址偏移量 (相對對象地址)valueOffset
static {
    try {
        valueOffset = unsafe.objectFieldOffset
            (AtomicInteger.class.getDeclaredField("value"));
    } catch (Exception ex) { throw new Error(ex); }
}

private volatile int value;

valueOffset表示的是變量值在內(nèi)存中相對對象偏移的地址,Unsafe根據(jù)內(nèi)存偏移地址獲取數(shù)據(jù)的原值述呐,這樣我們就能通過unsafe來實現(xiàn)CAS惩淳。

  1. 接下來研究Unsafe的getAndAddInt方法的實現(xiàn)
public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;
}
  1. 看著不直接,將變量替換以后
public final int getAndAddInt(Object atomicInteger, long offset, int addNumber) {
    int expect;
    do {
        // 根據(jù)對象和偏移量獲取內(nèi)存值
        expect = this.getIntVolatile(atomicInteger, offset);
    // 執(zhí)行CAS算法,如果不成功乓搬,則自旋到成功為止
    } while(!this.compareAndSwapInt(atomicInteger, offset, expect, expect + addNumber));

    return expect;
}
  1. Unsafe類中的compareAndSwapInt的native方法部分實現(xiàn)
    • 方法中先想辦法拿到變量value在內(nèi)存中的地址思犁。
    • 通過Atomic::cmpxchg實現(xiàn)原子性的比較和替換,其中參數(shù)x是即將更新的值进肯,參數(shù)e是內(nèi)存的值激蹲。至此,最終完成了CAS的全過程江掩。

compareAndSwapInt的native方法部分實現(xiàn).png

4) 缺點

  1. ABA問題:由于直接對比的為操作值学辱,檢查的內(nèi)存值可能被修改過,只不過剛好與本次期望值相同(顯然环形,標(biāo)準(zhǔn)庫中CAS算法的設(shè)計認(rèn)為ABA問題不影響我期望的操作)

    • 解決方式:添加版本號進(jìn)行比較(業(yè)務(wù)中在數(shù)據(jù)庫中進(jìn)行實現(xiàn))
  2. 自旋時間過長

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末策泣,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子抬吟,更是在濱河造成了極大的恐慌萨咕,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件火本,死亡現(xiàn)場離奇詭異危队,居然都是意外死亡聪建,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門茫陆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來金麸,“玉大人,你說我怎么就攤上這事盅弛∏睿” “怎么了叔锐?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵挪鹏,是天一觀的道長。 經(jīng)常有香客問我愉烙,道長讨盒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任步责,我火速辦了婚禮返顺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蔓肯。我一直安慰自己遂鹊,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布蔗包。 她就那樣靜靜地躺著秉扑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪调限。 梳的紋絲不亂的頭發(fā)上舟陆,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機(jī)與錄音耻矮,去河邊找鬼秦躯。 笑死,一個胖子當(dāng)著我的面吹牛裆装,可吹牛的內(nèi)容都是我干的踱承。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼哨免,長吁一口氣:“原來是場噩夢啊……” “哼茎活!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起铁瞒,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤妙色,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后慧耍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體身辨,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡丐谋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了煌珊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片号俐。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖定庵,靈堂內(nèi)的尸體忽然破棺而出吏饿,到底是詐尸還是另有隱情,我是刑警寧澤蔬浙,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布猪落,位于F島的核電站,受9級特大地震影響畴博,放射性物質(zhì)發(fā)生泄漏笨忌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一俱病、第九天 我趴在偏房一處隱蔽的房頂上張望官疲。 院中可真熱鬧,春花似錦亮隙、人聲如沸途凫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽维费。三九已至,卻和暖如春煤裙,著一層夾襖步出監(jiān)牢的瞬間掩完,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工硼砰, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留且蓬,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓题翰,卻偏偏與公主長得像恶阴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子豹障,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

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