不懂就问,关于 Java 并发 CAS 的问题

2019-10-07 16:56:08 +08:00
 Jacky23333
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;
    }

最近在看 JAVA 并发 CAS 的内容,看了源码之后不是很理解为什么它可以实现线程安全。

首先 var2 是对象在该线程里面的值,var5 是内存里面实际的值。compareAndSwapInt 只有在对比 var2 和 var5 相等的情况下才会将 var5+var4 的值更新到 var2 上面去。如果不相等则继续循环。

那现在的问题就是假设在进程 A 里面如果当 var2 等于 10 的时候,另外一个进程将新的值 20 写进内存中。那么此时 A 进程调用这个方法发现 var2=10 var5=20 两个值不相等那么继续循环。那么这种情况下什么时候才会跳出循环。无论怎么获取,getIntVolatile()得到的值永远都是 20 而 var2 的值永远都是 10,这样不是永远都不会相等吗?

第二个问题,有没有可能 A 进程里执行完 var5 = this.getIntVolatile(var1, var2);这句语句的时候,另外一个进程就把内存里面的值修改了。导致 var5 获得的值是个错误的值,但是 A 线程就拿着这个值去调用 compareAndSwapInt 方法,然后 var2 等于 var5 然后修改成功?

1035 次点击
所在节点    问与答
3 条回复
momocraft
2019-10-07 17:03:59 +08:00
如果这是 sun.misc.Unsafe: var2 是 obj 内的 offset, 不是比较或设置的值
Jacky23333
2019-10-07 17:11:31 +08:00
@momocraft 就是 un.misc.Unsafe 这个,var2 是 obj 内的 offset 这个什么意思,不是很懂,可以说详细一点吗
Jacky23333
2019-10-07 17:21:58 +08:00
@momocraft 弄懂了。谢谢老哥

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/606753

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX