什么是ABA问题
简单的一句话,狸猫换太子.
我们直到CAS中,对一个对象操作之前会先做比较,现在加入A拿到主内存中的一个变量10,B也同时拿到,而A线程的运行速度比较慢,假设为10s,B线程运行比较快,假设为2s,这样B线程可以先对10进行操作,比如说+1,并写入主内存,但A还没反应过来,B可以继续进行操作,再-1,这样主内存变量仍为10.这时A线程终于运行完成,也要对10进行操作,A会先比较自己拿到的值与主内存的值,相同,可以继续进行操作.但我们直到,A的10与主内存的10已经不是同一个了,这样的问题就是ABA问题。
package cn.edu.cas;
import java.util.concurrent.atomic.AtomicInteger;
public class ABADemo {
public static void main(String[] args) {
AtomicInteger a=new AtomicInteger(10);
new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"\t"+a);
a.compareAndSet(10,13);
System.out.println(Thread.currentThread().getName()+"\t"+a);
},"AA").start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"\t"+a);
a.compareAndSet(10,12);
System.out.println(Thread.currentThread().getName()+"\t"+a);
a.compareAndSet(12,10);
System.out.println(Thread.currentThread().getName()+"\t"+a);
},"BB").start();
}
}
可以看到两个线程A、B同时操作变量a,但由于A线程的执行速度很慢,当A去对a执行操作时,B已经操作了a多次,但由于结果碰巧不变,A再比对时,也以为没变化,并执行了操作。那么这种问题如何避免呢?
时间戳、版本号
这里涉及到原子引用
public static void main(String[] args) {
AtomicStampedReference<Integer> a=new AtomicStampedReference<>(10,1);
new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"\t"+a.getReference()+"\t"+a.getStamp());
a.compareAndSet(10,2019,1,2);
System.out.println(Thread.currentThread().getName()+"\t"+a.getReference()+"\t"+a.getStamp());
},"AA").start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"\t"+a.getReference()+"\t"+a.getStamp());
a.compareAndSet(10,12,1,2);
System.out.println(Thread.currentThread().getName()+"\t"+a.getReference()+"\t"+a.getStamp());
a.compareAndSet(12,10,2,3);
System.out.println(Thread.currentThread().getName()+"\t"+a.getReference()+"\t"+a.getStamp());
},"BB").start();
}
完美解决问题!