CAS個人理解

以下主要以AtomicInteger類中的方法描述CAS。

1、CAS是什麼

1)CAS即比較並交換,功能就是判斷內存某個位置是否爲預期值,如果是則更改爲新值,這個過程是原子的。簡單說CAS有3個操作數,內存值V,舊的預期值A,需要修改的更新值B,當且僅當預期值A和內存值V相同時,將內存值V修改爲B,否則什麼都不做。
2)AtomicInteger裏面的compareAndSet,getAndIncrement等底層也是CAS。

2、CAS底層

簡單說就是兩個:UnSafe、自旋鎖。
1)UnSafe
是CAS的核心類,UnSafe提供幾乎都是native方法,Java無法直接訪問底層系統,需要通過本地(native)方法來訪問,CAS操作涉及到硬件操作,所以就需要UnSafe類中的方法。
以getAndIncrement方法爲例

public final int getAndIncrement() {
    return unsafe.getAndAddInt(this, valueOffset, 1);
}
  • this表示當前對象
  • 變量valueOffset,表示該變量在內存中的偏移地址,UnSafe根據內存偏移地址獲取數據。

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;
}
  • var1:AtomicInteger對象本身
  • var2:該對象值的引用地址
  • var4:需要變動的數量
  • var5:使用過var1、var2找出的主內存中真實的值

用當前對象的值與var5比較,如果相同,更新var5 + var4並且返回ture,如果不同,繼續while循環,繼續取值然後在再比較,直到更新完成。

3、CAS缺點

1)循環時間長開銷很大,底層是do while循環,自旋。
2)只能保證一個共享變量的原子操作,當多個共享變量操作時,循環CAS就無法保證操作的原子性,這個時候可以用鎖來保證原子性。
3)ABA問題
比如說一個線程one從內存位置V取出A,這個時候另一個線程two也從內存中取出A,並且進行了一些操作將值變成了B,然後線程two又將位置的數據變成A,這時候線程one進行CAS操作發現內存中仍然是A,然後線程操作成功。儘管線程A操作成功,但是不代表這個過程是沒有問題的。
可用時間戳或者版本解決,例如JUC裏面的AtomicStampedReference

發佈了71 篇原創文章 · 獲贊 37 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章