简介
上一篇文章详细讲解了AtomicInteger原子类,还有和AtomicInteger原子类实现原理基本一样的AtomicLong和AtomicBoolean原子类。这些都是基本数据类型的原子类,在并发情景下可以保证基本数据类型变量的原子性。但是对于引用类型,这些基本类型的原子类就无能为力了,所以就出现对象引用类型的原子类。
对象引用类型的原子类包括:AtomicReference、AtomicStampedReference、AtomicMarkableReference
AtomicReference原子类与基本数据类型的原子类实现过程相似,故不再赘述。
不过值得注意的是,使用CAS会有ABA的隐患!什么是ABA?知乎用户对ABA相关的提问
所以AtomicStampedReference、AtomicMarkableReference两个原子类就大派用场啦!
AtomicStampedReference 的使用
先看下AtomicStampedReference 原子类的核心源码:
public class AtomicStampedReference<V> {
// Pair对象维护对象的引用和对象标志的版本,通过Pair对象解决“ABA”问题
private static class Pair<T> {
final T reference;// 对象的引用
final int stamp;// 对象标志的版本
private Pair(T reference, int stamp) {
this.reference = reference;
this.stamp = stamp;
}
static <T> Pair<T> of(T reference, int stamp) {
return new Pair<T>(reference, stamp);
}
}
private volatile Pair<V> pair;
public AtomicStampedReference(V initialRef, int initialStamp) {
pair = Pair.of(initialRef, initialStamp); }
public V getReference() {
return pair.reference; }
public int getStamp() {
return pair.stamp; }
public V get(int[] stampHolder) {
Pair<V> pair = this.pair;
stampHolder[0] = pair.stamp;
return pair.reference;
}
public boolean weakCompareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
return compareAndSet(expectedReference, newReference,
expectedStamp, newStamp);
}
/**
* @param expectedReference 期待的原始对象
* @param newReference 将要更新的对象
* @param expectedStamp 期待原始对象的标志版本
* @param newStamp 将要更新对象的标志版本
*/
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
return
expectedReference == current.reference && // 如果返回true则说明期待的原始对象与Pair的reference对象一样
expectedStamp == current.stamp && // 如果返回true说明期待原始对象标志版本与Pair的stamp对象一样
((newReference == current.reference &&
newStamp == current.stamp) || // 如果期待更新的对象和标志版本与Pair的reference和stamp一样的话直接返回true,否则执行CAS操作
casPair(current, Pair.of(newReference, newStamp))