什么是ABA问题?
解决方案:引入原子引用,AtomicStampedReference
import java.util.concurrent.TimeUnit;所有整型包装类对象之间值的比较,全部使用 equals 方法比较。 说明:对于 Integer var = ? 在-128 至 127 之间的赋值,Integer 对象是在 IntegerCache.cache 产生, 会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,都 会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。 如果上面例子中的原子引用接口的参数值范围不在-128-127之间,就会存在问题。
import java.util.concurrent.atomic.AtomicStampedReference;
public class AtomicReferenceDemo {
public static void main(String[] args) {
AtomicStampedReference<Integer> atomic = new AtomicStampedReference<Integer>(1, 1);
new Thread(()->{
int stamp = atomic.getStamp();
System.out.println("a1=>" + stamp);
//延时2秒,保证A,线程进来后取得的版本号一致
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A------");
System.out.println(atomic.compareAndSet(1, 2, atomic.getStamp(), atomic.getStamp() + 1));
System.out.println("a2=>" + atomic.getStamp());
System.out.println("A------");
System.out.println(atomic.compareAndSet(2, 1, atomic.getStamp(), atomic.getStamp() + 1));
System.out.println("a3=>" + atomic.getStamp());
}, "a").start();
new Thread(()->{
int stamp = atomic.getStamp();
System.out.println("b1=>" + stamp);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B------");
System.out.println(atomic.compareAndSet(1, 6, stamp, stamp + 1));
System.out.println("b2=>" + atomic.getStamp());
}, "b").start();
}
}
这里需要注意的是,对于包装类Integer有个大坑,详见阿里巴巴java开发手册: