CAS是compareAndSwap的簡稱,它可以幫助我們實現多線程執行的安全性。
CAS有三個操作數:內存值V、舊的預期值A、要修改的值B,當且僅當預期值A和內存值V相同時,將內存值修改爲B並返回true,否則什麼都不做並返回false。雖然步驟分爲兩筆,比較和賦值,但CAS是在native層的unsafe類中實現的,屬於硬件級別的操作,同樣可以保證原子性。
下面是compareAndSwapInt方法:
public final native boolean compareAndSwapInt(Object paramObject, long paramLong, int paramInt1, int paramInt2);
第一個參數Object是要修改的對象,第二個參數是要修改的變量在存儲Object的內存中偏移量,通過這兩個參數定位要修改的變量,第三個參數是修改之前的值,第四個參數是預期修改之後的值。
java.util.concurrent包中的atomic就是使用CAS保證原子性的。
CAS缺點
CAS存在一個很明顯的問題,即ABA問題。
如果變量V初次讀取的時候是A,並且在準備賦值的時候檢查到它仍然是A,那能說明它的值沒有被其他線程修改過了嗎?如果在這段期間它的值曾經被改成了B,然後又改回A,那CAS操作就會誤認爲它從來沒有被修改過。針對這種情況,java併發包中提供了一個帶有標記的原子引用類"AtomicStampedReference",它可以通過控制變量值的版本來保證CAS的正確性。