多线程情况下演示AtomicStampedReference解决ABA问题
package com.nanjing.gulimall.zhouyimo.test;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;
/**
* @author zhou
* @version 1.0
* @date 2024/1/3 10:07 下午
*/
public class ABADemo {
private static AtomicInteger atomicInteger = new AtomicInteger(100);
private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100,1);
public static void main(String[] args) {
new Thread(()->{
int stamp = atomicStampedReference.getStamp();
System.out.println(Thread.currentThread().getName()+"----"+"首次版本号:"+stamp);
try {
//暂停500毫秒,保证后面的t4线程初始化拿到的版本号和我一样
TimeUnit.MICROSECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
atomicStampedReference.compareAndSet(100, 101, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
System.out.println(Thread.currentThread().getName() + "\t" + "2次版本号: " + atomicStampedReference.getStamp());
atomicStampedReference.compareAndSet(101, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
System.out.println(Thread.currentThread().getName() + "\t" + "3次版本号: " + atomicStampedReference.getStamp());
},"t3").start();
new Thread(()->{
int stamp = atomicStampedReference.getStamp();
System.out.println(Thread.currentThread().getName()+"----"+"首次版本号:"+stamp);
try {
//暂停1秒,等待上面t3线程,发生ABA问题
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean b = atomicStampedReference.compareAndSet(100, 2024, stamp, stamp + 1);
System.out.println(b + "\t" + atomicStampedReference.getReference() + "\t" + atomicStampedReference.getStamp());
},"t4").start();
/*
t3----首次版本号:1
t4----首次版本号:1
t3 2次版本号: 2
t3 3次版本号: 3
false 100 3 此时提交作废,已经被人动过了
*/
}
private static void abaHappen() {
new Thread(() ->{
atomicInteger.compareAndSet(100,101);
try {
TimeUnit.MICROSECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
atomicInteger.compareAndSet(101,100);
},"t1").start();
new Thread(() ->{
try {
//为了保证让上面先发生ABA问题,先睡眠200毫秒
TimeUnit.MICROSECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicInteger.compareAndSet(100,2024)+"----"+atomicInteger.get());//true----2024
},"t2").start();
}
}
一句话总结:比较加版本号一起上