CAS 的問題

cas這麼好用,那麼有沒有什麼問題呢?還真有
ABA問題
CAS須要在操做值的時候檢查下值有沒有發生變化,若是沒有發生變化則更新,可是若是一個值原來是A,變成了B,又變成了A,那麼使用CAS進行檢查時會發現它的值沒有發生變化,可是實際上卻變化了。這就是CAS的ABA問題。 常見的解決思路是使用版本號。在變量前面追加上版本號,每次變量更新的時候把版本號加一,那麼A-B-A 就會變成1A-2B-3A。 目前在JDK的atomic包裏提供了一個類AtomicStampedReference來解決ABA問題。這個類的compareAndSet方法做用是首先檢查當前引用是否等於預期引用,而且當前標誌是否等於預期標誌,若是所有相等,則以原子方式將該引用和該標誌的值設置爲給定的更新值。
循環時間長開銷大
上面咱們說過若是CAS不成功,則會原地循環(自旋操做),若是長時間自旋會給CPU帶來很是大的執行開銷。併發量比較大的狀況下,CAS成功機率可能比較低,可能會重試不少次纔會成功。
 
解決ABA最簡單的方案就是給值加一個修改版本號,每次值變化,都會修改它版本號,CAS操做時都對比此版本號
 

JAVA中ABA中解決方案(AtomicStampedReference)

AtomicStampedReference主要維護包含一個對象引用以及一個能夠自動更新的整數"stamp"的pair對象來解決ABA問題。
AtomicStampedRerence正是這麼作的,他內部不只維護了對象的值,還維護了一個時間戳(咱們這裏把他稱爲時間戳,實際上它可使用任何一個整形來表示狀態值),當AtomicStampedRerence對應的數值被修改時,除了更新數據自己外,還必需要更新時間戳。當AtomicStampedRerence設置對象值時,對象值及時間戳都必須知足指望值,寫入纔會成功。所以,即便對象值被反覆讀寫,寫回原值,只要時間戳發生變量,就能防止不恰當的寫入
相關文章
相關標籤/搜索