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等指令產生臨界...