关于ABA问题

来源:3-2 线程安全性-原子性-atomic-2

blanc_

2018-07-20

线程2将内存中的值A取出来变成了B,然后又改回成了A,没理解为什么线程2要做这种操作

比如内存中是2 ,线程B的工作内存中也是2,满足cas条件,所以B会把主存中的值修改为3,皆大欢喜,但是为什么又要改回2?

还有一个问题 假设线程1 做do操作时内存取出主存中的值var5=1  自己工作内存中的var2是也是var2 =1 

但是在执行while(!thiscompareandswapint())之前  有另一个线程2 do取出的主存中的值var5 = 1 ,

自己工作内存中的var2 也是 var2 =1,所以满足cas并且他做了cas操作 , 再回来看线程1  他执行cas里的var5 还是do方法取出的1 ,所以也满足cas操作,但是时间上var5的值已经被线程2修改为2了,不懂这之中是什么道理 难道在cas操作中又从主存中取了一次var5么 ? 不然怎么保证一个线程do取var5  和 while这之间的时间一定是没问题的呢

   

写回答

1回答

Jimin

2018-07-20

你好,你这问题到是很有意思,我挨个说一下。

先说第一个问题,你这里提到的“为什么又要改回2”,其实这时候不是他要不要的问题,而是某些情况下导致当前数据和之前某次操作完之前相同,这时候如果不通过版本来管理,是有一定几率丢掉中间的操作,导致对最终的结果造成一定的影响。例子可以参考这篇文章里说的链表实现的堆栈问题:https://www.cnblogs.com/549294286/p/3766717.html

再来说第二个问题,我们先来看底层实现,

public final int getAndAddInt(Object var1, long var2, int var4) {
   int var5;
   do {
       var5 = this.getIntVolatile(var1, var2);
   } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

   return var5;
}

这里是个do...while循环,当compareAndSwapInt这个方法返回false时,代表实际的值和当前线程里的值已经不一样了,这时会重新取出var5这个变量,而且是通过getIntVolatile保证取到最新的值,这时修正compareAndSwapInt里传入的变量,继续尝试。如果不成功,则继续取出最新的值去处理,直到成功为止。

1
3
kimvra
回复
zhusx
我的理解是,在执行compareandswap的时候,还会用var1和var2去取到实际的底层的值,也就是这个时候取到的值才是最新最新的,所以用最新的值和之前取到的var5作比较能判断是否被其他线程修改过。
2019-01-16
共3条回复

Java高并发编程,构建并发知识体系,提升面试成功率

构建完整并发与高并发知识体系,倍增高薪面试成功率!

3923 学习 · 832 问题

查看课程