并发包源码解读——AtomicReference&AtomicMarkableReference&AtomicStampedReference
1、AtomicReference
对象原子类,简单的cas
也同时包含getAndUpdate、getAndAccumulate等方法,都是cas不多赘述
AtomicReference<String> atomic = new AtomicReference<>("abc");
String expect = atomic.get();
//TODO:做了一些比较耗时的工作
boolean success = atomic.compareAndSet(expect, "abcd");
2、AtomicStampedReference
提供了一个stamp版本号,来判断版本是否改变过,解决ABA问题
AtomicStampedReference<String> atomicStamped = new AtomicStampedReference<>("abc", 0);
String expect = atomicStamped.getReference();
int stamp = atomicStamped.getStamp();
//TODO:做了一些比较耗时的工作
boolean success = atomicStamped.compareAndSet(expect, "abcd", stamp, stamp + 1);
AtomicStampedReference里面维护的是一个Pair
表面上是通过值对象和版本号cas,实际上就是把值对象和版本号又封装成了一个对象
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
return
//期待值得跟Pair里的值相同
expectedReference == current.reference &&
//期待版本号得跟Pair里的版本号相同
expectedStamp == current.stamp &&
//新值没变或者版本号没变就返回true
((newReference == current.reference &&
newStamp == current.stamp) ||
//cas成功返回true
casPair(current, Pair.of(newReference, newStamp)));
}
3、AtomicMarkableReference
AtomicMarkableReference不会记录版本变了几次,只会记录值更没更新,给了一个mark作为标识
AtomicMarkableReference<String> atomicMarkable = new AtomicMarkableReference<>("abc", false);
String reference = atomicMarkable.getReference();
boolean marked = atomicMarkable.isMarked();
//TODO:做了一些比较耗时的工作
atomicMarkable.compareAndSet(reference,"abcd", marked,true);
跟AtomicStampedReference同理
public boolean compareAndSet(V expectedReference,
V newReference,
boolean expectedMark,
boolean newMark) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
expectedMark == current.mark &&
((newReference == current.reference &&
newMark == current.mark) ||
casPair(current, Pair.of(newReference, newMark)));
}