CAS如何實現原子性與ABA問題

2021-10-19 22:54:21 字數 1873 閱讀 1234

cas 全稱是 compare and swap(比較並且交換),是一種用於在多執行緒環境下實現同步功能的機制,其也是無鎖優化,或者叫自旋,還有自適應自旋(說法不算準確,底層還是存在鎖,後面會講)。

//以atomicinteger類的compareandset方法舉例。

//其原始碼:

//expect與舊值一致,則用update替換舊值

public final boolean compareandset(int expect, int update)

問題:cas是原子性的嗎?從上面的compareandset方法為例,需要先與舊值比較,然後再替換舊值,那是不是代表是兩個操作呢?下面從原始碼開始分析:1)compareandset原始碼呼叫unsafe.compareandswapint:

//unsafe這個類大部分方法都是native,呼叫底層c的**。

public

final

native

boolean

compareandswapint

(object var1,

long var2,

int var4,

int var5)

;

2)compareandswapint在c++層面的原始碼:

其核心指令:atomic::cmpxchg(x,addr,e),cmpxchg是compare和exchange縮寫。

3)彙編實現:atomic::cmpxchg(x,addr,e)

在彙編層面,在多執行緒中,比較與交換操作加了一把lock鎖,鎖住了比較與交換這兩個操作,所以在這個過程中是原子性的。

4)多看乙個指令,獲取lock指令的方法:lock_if_mp

因為cas底層呼叫的彙編命令atomic::cmpxchg,在多執行緒情況下,會加鎖,所以確保了比較並交換操作的原子性。

//以下假設有兩個執行緒

integer oldvalue =1;

//執行緒1要修改oldvalue=2

//此時執行緒2進來,將oldvalue改值:1->0->1,

oldvalue =0;

oldvalue =1;

atomicinteger.

compareandset(1

,2);

//執行緒1執行

//執行緒1不知道執行緒2改過這個值,因為這一條**直接判斷oldvalue=1,

//是正確的,所以正常的執行oldvalue=2.

如何解決?新增版本號:為要修改的資源新增版本號,每修改一次,版本號+1,然後cas操作時,校驗這個版本號,版本號相同,才能進行cas,否則失敗。

為要修改的資源新增版本號,每修改一次,版本號+1,然後cas操作時,校驗這個版本號,版本號相同,才能進行cas,否則失敗。

例如上面的例子,為oldvalue新增乙個版本號version=1,當執行緒2修改1:(version=1)->0:(version=2)->1:(version=3)後,此時版本號應該version=3,而執行緒1執行cas,就比較此時是否version=1,如果不等,那麼不允許進行cas操作。

CAS又是怎樣保證原子性的?

a.什麼是cas?1 全稱是compareandset,含義是比較並交換。2 cas有3個運算元,記憶體值v,舊的預期值a,要修改的新值b。當且僅當預期值a和記憶體值v相同時,將記憶體值v修改為b,否則返回v b.下面來看下atomicinteger.incrementandget 的原始碼 pub...

多執行緒原子性 CAS以及ABA問題

通常情況下為了保證安全,在乙個執行緒對乙個數值訪問時要上鎖,但是為了保證效率,cas中是不上鎖的。列如 現在有乙個值為0,讀取這個值,並且將其存在e中,則 e 0。然後對e進行遞增運算,有計算結果設為v。e 後,設乙個新的值為n 即 n e 這時去檢視e,如果e還是為0,則表明沒有其他的執行緒修改e...

原子性atomic與非原子性natomic

原子操作是不可分割的操作,在原子操作執行完畢之前,其不會被任何其它任務或事件中斷。在單處理器系統 uniprocessor 中,能夠在單條指令中完成的操作都可以認為是 原子操作 因為中斷只能發生於指令之間。某些cpu指令系統中引入了test and set test and clear等指令產生臨界...