Java 非易失场原子CAS 如果我们考虑下面的类和x86体系结构: class Foo{ int x; void increment() { compareAndSwap(x, x+1); } int getX() { return x; } }

Java 非易失场原子CAS 如果我们考虑下面的类和x86体系结构: class Foo{ int x; void increment() { compareAndSwap(x, x+1); } int getX() { return x; } },java,concurrency,atomic,volatile,compare-and-swap,Java,Concurrency,Atomic,Volatile,Compare And Swap,如果我们现在假设一个线程正在调用increment,而另一个线程定期调用get,那么读者是否有可能看不到X的更新版本?compareAndSwap是否应该在缓存之间锁定缓存线,在比较后更新值,然后触发一个完整的屏障?我认为答案是:这取决于 在底层jvm实现上-分别比较您在没有进一步定义的情况下引入的AndSwap 换句话说:我认为正确的compareAndSwap实现应该考虑缓存线是合理的 这就是jvm为您提供保证的全部意义,不是吗。如果jvm由于CPU缓存而给出不一致的结果,那么这种保证会给我

如果我们现在假设一个线程正在调用increment,而另一个线程定期调用get,那么读者是否有可能看不到X的更新版本?compareAndSwap是否应该在缓存之间锁定缓存线,在比较后更新值,然后触发一个完整的屏障?

我认为答案是:这取决于

在底层jvm实现上-分别比较您在没有进一步定义的情况下引入的AndSwap

换句话说:我认为正确的compareAndSwap实现应该考虑缓存线是合理的

这就是jvm为您提供保证的全部意义,不是吗。如果jvm由于CPU缓存而给出不一致的结果,那么这种保证会给我们提供什么样的帮助

含义:Java内存模型的全部要点是提供某些“固定”的保证。如果CPU缓存可以破坏它们,那么它们将是无用的


但我也同意给出的评论——变量不是易变的这一事实意味着不同的线程实际上可能会看到x的“不同”值

读卡器线程绝对有可能看不到更新后的值
x
。确保获得最新的
x
volatile
的主要目的之一

联合联络小组第17章讨论了这一点。具体来说,请查看:

:

如果对同一变量的两次访问(读取或写入)中至少有一次是写入,则称为冲突

以及:

当一个程序包含两个冲突的访问(§17.4.1),而这两个访问不是由“先发生后发生”关系排序时,则称其包含数据竞争

我不会列出关于如何建立“先发生后发生”关系的所有细节(在17.4.5中有详细说明),但我只想说,在没有同步的情况下访问非易失性字段并不能做到这一点

这意味着你的代码有一个数据竞争,这意味着很多赌注都没有了。例如,JVM不需要为操作提供单一的顺序;您可以让一个线程看到一个订单,另一个线程看到另一个订单

引用我的最后一点JLS,这次来自:

顺序一致性是程序执行过程中可见性和顺序的有力保证。在顺序一致的执行中,所有单独操作(如读写)的总顺序与程序的顺序一致,每个单独操作都是原子的,每个线程都可以立即看到。(增加重点)

这就是你想要的,只有在你的代码没有数据竞争的情况下,你才能保证拥有它。这与您的问题有关,因为在没有顺序一致执行的情况下,读线程基本上可以按照“所有其他操作(包括读取),然后是写入”的顺序进行排序——这意味着它永远不会看到读取——即使其他线程在不将写入延迟到无穷大的情况下继续执行

当人们试图创建一个
boolean stop
变量来表示线程应该停止,但忽略了使其不稳定时,通常会出现这种情况。有时它是有效的;很多时候,该线程将永远旋转,因为它从未看到写入
停止


另请参见关于使用
volatile
关键字。

什么是
compareAndSwap()
的定义?也就是说,这是伪代码还是实际的可编译Java?我不记得不安全的方法签名,但基本上是不安全方法的伪代码。我注意到您的问题仍然是“开放的”——因为您没有接受答案。请看一看,然后决定是否要回答。或者让我知道是否有什么我可以做的,以加强我的投入,使其值得接受。接受帮助未来的读者确定问题是否得到解决,并对花时间回答你的人表示感谢。谢谢但是
x
不是易变的,因此这是一场数据竞争(假设多个线程正在调用
increment()
),这意味着基本上所有的赌注都在保证方面失败了。几乎你能得到的唯一保证是
x
将是默认的0或你写的某个值(即,你不会得到单词撕裂)。但这是什么价值呢。。。JVM基本上可以做它想做的任何事情。听说过不安全类吗?该类包含比较和交换方法。如果您使用它,很可能在不使用volatile的情况下实现该结果。因此,“这取决于具体细节”。当然,如果JVM愿意,它可以提供额外的保证。但是JLS和JVM规范(据我所知)都没有做出任何这样的保证,所以说“Java”做出这些保证是一种延伸,依我看。我的主要问题是,如果不添加volatile,x可能会存储在寄存器中,并且永远不会从mem或缓存中重新读取?除非您确切指定使用什么JVM,以及如何使用实现了“compareAndSwap”——没有人能给你一个准确的答案。当某个东西不易波动时,你无法保证它的“位置”(以及潜在的“拷贝数”)。