假设以下代码:
class X {
private int v = 1;
public void set(int v) { this.v = v; }
public int get() { return v; }
}
是否有可能通过未将 v
标记为 volatile ,在调用 set(123)
时,其值不会传播到其他内核(即它们的缓存)和/或主内存),或者这只是时间问题?
通过询问,一般的想法似乎是迟早该值“会到达那里”,因此只要我们不太关心时间精度,就可以让该值保持非 volatile ,但我想正式确定。
我的理解是,由于没有获取/释放语义,JMM 不保证它能够工作,但另一方面,我对缓存一致性/一致性模型(即 TSO-x86)的(有限)理解是它最终必然会传播(将其标记为 volatile 只会设置一个栅栏以禁止在 CPU 的存储缓冲区中重新排序,但除此之外它最终会传播到其他缓存)。关于这一点,只有一点让我想知道——如果另一个核心向同一缓存行中的另一个变量写入内容会发生什么?在任何情况下它都能覆盖v
吗?
任何了解此事的人都可以给我更具体的答案吗?
谢谢!
最佳答案
根据memory model JVM 中没有 happens-before你的例子中的关系。因此,从形式上讲,不能保证另一个线程会看到共享变量的更新。
依赖特定 JVM 和处理器架构的实现细节对我来说似乎不是一个好主意。今天在实验室有效的方法可能明天在现场就会失败。另请注意,最终可能会很长,因为没有上限。事实上,我遇到过这样的情况:我的程序似乎由于缺少 volatile
注释而被阻止,并且必须重新启动。
关于multithreading - JVM/x86 是否保证跨内核的值的非 volatile 传播?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56001665/