关于public final int getAndAddInt(Object var1, long var2, int var4) 方法的一个问题

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

磊磊要酷酷滴

2019-03-27

  • var5 = this.getIntVolatile(var1, var2); 从主内存中取出了共享变量count的最新值到当前线程的本地变量var5中;
  • 那么在var5 = this.getIntVolatile(var1, var2); 和 this.compareAndSwapInt(var1, var2, var5, var5 + var4)之间别的线程也会更新主内存中的count,导致var5和主内存中的count不一致,var5岂不是不能保证就是最新的主内存中count的副本吗?
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;
}
写回答

2回答

Jimin

2019-03-27

你好,var5只能保证取出的是当时内存里最新的值,不保证之后调用compareAndSwapInt

时依旧和内存里的值仍然一致。本身取出var5最新值后去调用compareAndSwapInt也不一定直接成功,就因为这两个操作本身不具备原子性。但这并不影响 getAndAddInt 整个方法要完成的事情,这个原因在于:


首先,compareAndSwapInt 这个native方法涉及到的”检查相等则更新,否则不更新“这两个操作是原子性的,cpu指令来保证。


其次,getIntVolatile 和 compareAndSwapInt 这两个操作中间确实可能有其他操作,也就是var5刚从内存取了一次,内存里的值就更新了。但是他不是只做一次的。compareAndSwapInt会去检查当前线程里获取的值和内存里最新的值是否相等,只要不等就继续重新获取var5的最新值并重试这个过程,直到相等才进行更新。


实际中,getIntVolatile和compareAndSwapInt 两个操作中间尽管会插入其他操作,但要重试好几次的概率其实很小,这里不需要纠结一直会重试下去的可能,这里只能说理论上有可能会重试很多次,实际会很快退出重试的。


0
1
磊磊要酷酷滴
这次是真的扫除了我理解上的误区了,var5不是和var1比,而是和内存中的最新值比,扫清了这个误区,就豁然开朗了。谢谢老师的耐心解答^_^
2019-03-29
共1条回复

Turren

2019-03-27

0
2
Jimin
回复
磊磊要酷酷滴
每个人的理解多少都有些差异,因此一份回答不一定能满足所有人,你可以看看我针对你这个提问点的回答,是否能解答你的疑问,之前很多人是纠结compareAndSwapInt的原子性,因为这个方法有问题。
2019-03-27
共2条回复

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

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

3923 学习 · 832 问题

查看课程