本博客系列是學習並發編程過程中的記錄總結。由於文章比較多,寫的時間也比較散,所以我整理了個目錄貼(傳送門),方便查閱。
並發編程的基石——CAS機制這篇文章中介紹到CAS機制有一個缺點就是ABA問題:CAS在操作的時候會檢查變量的值是否被更改過,如果沒有則更新值,但是帶來一個問題是:如果值最開始的值是A,接着變成B,最后又變成了A。經過檢查這個值確實沒有修改過,因此CAS機制會更新這個值。但是實際上這個值已經被修改過了。
AtomicStampedReference
和AtomicMarkableReference
就是用來解決CAS中的ABA問題的。他們解決ABA問題的原理類似,都是通過一個版本號來區分有沒被更新過。
- AtomicStampedReference:帶版本戳的原子引用類型,版本戳為int類型。
- AtomicMarkableReference:帶版本戳的原子引用類型,版本戳為boolean類型。
AtomicStampedReference使用列子
public class AtomicStampedReferenceDemo {
private static Long var = new Long(1);
public static void main(String[] args) {
AtomicStampedReference<Long> referenceDemo = new AtomicStampedReference(var,1);
System.out.println("now value:"+referenceDemo.getReference().intValue());
int stamp = referenceDemo.getStamp();
System.out.println("now stamp:"+stamp);
boolean b = referenceDemo.compareAndSet(var, new Long(2), stamp, stamp + 1);
if(b){
System.out.println("success set value...");
System.out.println("now value:"+referenceDemo.getReference().intValue());
stamp = referenceDemo.getStamp();
System.out.println("now stamp:"+stamp);
}else {
System.out.println("failed set value...");
System.out.println("now value:"+referenceDemo.getReference().intValue());
stamp = referenceDemo.getStamp();
System.out.println("now stamp:"+stamp);
}
}
}
AtomicMarkableReference使用
關於AtomicMarkableReference的原理其實是與AtomicStampedReference類似的。
區別是AtomicMarkableReference的版本戳是boolean類型,所以導致版本狀態只有兩個:true或者false。
所以,我更傾向於稱呼AtomicMarkableReference為帶標記的原子引用類型。
- 版本戳 = true,表示此引用被標記。
- 版本戳 = false,表示此引用未被標記。