AtomicInteger,AtomicBoolean,AtomicReference都是根据value的是否变化来做cas修改的,但是这样无法解决ABA的问题
AtomicStampedReference类不仅比较了对象还比较了版本号
AtomicStampedReference的使用
Object obj = new Object();
int initialStamp = 0;
AtomicStampedReference atomicStampedReference = new AtomicStampedReference(obj,initialStamp);
System.out.println(atomicStampedReference.getStamp());
//修改对象的引用和版本号
Object reference = atomicStampedReference.getReference();
int stamp = atomicStampedReference.getStamp();
atomicStampedReference.weakCompareAndSet(reference, new Object(), stamp, stamp + 1);
System.out.println(atomicStampedReference.getStamp());
构造方法
public AtomicStampedReference(V initialRef, int initialStamp) {
pair = Pair.of(initialRef, initialStamp);
}
//Pair是AtomicStampedReference的内部类,它保存了一个持有的对象reference和版本号stamp
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);
}
}
设置新对象
public boolean weakCompareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
return compareAndSet(expectedReference, newReference,
expectedStamp, newStamp);
}
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
return
//比较旧引用,当expectedReference != 对象当前的reference时,说明该数据肯定被其他线程修改过
expectedReference == current.reference &&
//比较旧版本,进一步比较expectedStamp是否等于对象当
前的版本号,以此判断数据是否被其他线程修改过
expectedStamp == current.stamp &&
//这里比较新引用和新版本,如果相等,则不需要修改了
((newReference == current.reference &&
newStamp == current.stamp) ||
//cas修改Pair
casPair(current, Pair.of(newReference, newStamp)));
private boolean casPair(Pair<V> cmp, Pair<V> val) {
//this:AtomicStampedReference
//pairOffset:pair的偏移量
//cmp:旧对象
//val:新对象
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
}