一、ABA问题?
当我们使用CAS自旋
的方式对一个值进行修改操作
时,若修改成功
就代表变量没有被修改过,真的是这样吗?
场景:
1. main主线程
要修改变量的值A
修改为 值C
,在修改之前会判断变量的值是否
进行了修改
2. 在main主线程
修改变量前
,线程1
把变量值A
修改为 值B
3. 接下来线程2
在main主线程前
将 值B
修改为 值A
4. 轮到main主线程
,主线程将变量修改之前
判断,发现变量没有被改变还是 值A
,那么main主线程修改成功,将变量 修改为 值C
5. 但是,变量的值被其他线程进行了更改,这就是ABA问题
static AtomicReference<String> ref = new AtomicReference<>("A");
public static void main(String[] args) throws Exception{
System.out.println("main主线程 start...");
//获取值A
String prev =ref.get();
other();
Thread.sleep(1000);
//尝试将值A 修改为 值C
ref.compareAndSet(prev, "C");
System.out.println("main主线程修改值后的newVal===>"+ref.get());
}
public static void other()throws Exception{
new Thread(()->{
//t1线程将值改成B
ref.compareAndSet(ref.get(),"B");
System.out.println("t1线程修改值后的newVal===>"+ref.get());
},"t1").start();
Thread.sleep(500);
new Thread(()->{
//t2线程将值回改为A
ref.compareAndSet(ref.get(),"A");
System.out.println("t2线程修改值后的newVal===>"+ref.get());
},"t2").start();
}
上方文字以及代码的执行结果如下图
二、解决ABA问题
使用原子引用
在CAS自旋的基础上添加版本号
static AtomicStampedReference<String> ref = new AtomicStampedReference<String>("A",0);
public static void main(String[] args) throws Exception{
System.out.println("main主线程 start...");
//获取值A
String prev = ref.getReference();
//获取版本号
int version = ref.getStamp();
other();
Thread.sleep(1000);
//对比值和版本号 尝试将值A 修改为 C
boolean result=ref.compareAndSet(prev, "C",version,version+1);
System.out.println("main主线程修改值后的A===>B "+result);
}
public static void other()throws Exception{
new Thread(()->{
//t1线程获取版本号
int version = ref.getStamp();
//t1线程将值改成B
boolean result=ref.compareAndSet(ref.getReference(),"B",version,version+1);
System.out.println("t1线程修改值后A===>B "+result);
},"t1").start();
Thread.sleep(500);
new Thread(()->{
//t2线程获取版本号
int version = ref.getStamp();
//t2线程将值回改为A
boolean flag=ref.compareAndSet(ref.getReference(),"A",version,version+1);
System.out.println("t2线程修改值后B===>A "+flag);
},"t2").start();
}
执行结果:
- 另外一种简洁的方式来
解决ABA
问题
使用AtomicMarkableReference
类,与AtomicStampedReference
类似,只不过AtomicMarkableReference
使用的是通过true或者false
来判断变量的值是否被其他线程修改
总结
浅谈ABA问题以及解决方案。