ABA:当线程1要将A->C,但是其他线程在线程1执行过程中将A->B,然后又将B->A,这时候线程1cas时会成功执行,但是无法判断A是已经被改过的.
解决: AtomicStampedReference通过这个原子类,使用版本号的方式解决ABA问题.
static AtomicStampedReference<String> ref = new AtomicStampedReference<>("A", 0);
public static void main(String[] args) throws InterruptedException {
String prev = ref.getReference();
int stamp = ref.getStamp();
// 如果中间有其它线程干扰,发生了 ABA 现象
other();
sleep(1);
log.debug("change A->C {}", ref.compareAndSet(prev, "C", stamp, stamp + 1));
}
//其他线程执行A->B,B->A
private static void other() {
new Thread(() -> {
log.debug("change A->B {}", ref.compareAndSet(ref.getReference(), "B",
ref.getStamp(), ref.getStamp() + 1));
}, "t1").start();
sleep(0.5);
new Thread(() -> {
log.debug("change B->A {}", ref.compareAndSet(ref.getReference(), "A",
ref.getStamp(), ref.getStamp() + 1));
}, "t2").start();
}
通过设置一个版本,来确定A的值是否被修改过。cas时通过版本号的值判断,如果版本号发生变化,cas的操作就会返回false,这样就解决了ABA问题.