关于如何 Java 在新内存模型 (JSR 133) 中实现 volatile 的谜题
A puzzle on how Java implement volatile in new memory model (JSR 133)
在JSR 133 Java Memory Model FAQ中,它表示
the new memory model places stricter constraints on reordering of
volatile field accesses with other field accesses, volatile or not,
anything that was visible to thread A when it writes to volatile field
f becomes visible to thread B when it reads f
它还给出了如何使用可变字段的示例
class VolatileExample {
int x = 0;
volatile boolean v = false;
public void writer() {
x = 42;
v = true;
}
public void reader() {
if (v == true) {
//uses x - guaranteed to see 42.
}
}
}
在上面的代码中,JVM(JIT?)会在 v
的负载和 x
的负载之间插入一个 LoadLoad
内存 barrier/fence reader()
,指的是The JSR-133 Cookbook for Compiler Writers(实际实现取决于底层CPU架构)
并且硬件使用缓存一致性协议来确保 L1,2... 缓存和主内存之间的一致性。
但我猜想这些机制似乎不够充分。为了保证在 reader()
中看到 42
,JVM(JIT)是否必须从主内存(或 L1)读取 v
(非易失性)和 x
(易失性) ,2.. 由硬件控制的缓存)而不是 CPU 寄存器?
是否有任何链接或文档显示 JVM 如何实现新内存模型的详细信息? The JSR-133 Cookbook for Compiler Writers只展示了内存屏障是如何使用的,而没有提到缓存(在寄存器,L1,2..缓存,主内存中)。
JSR-133 Cookbook 中提到的 LoadLoad
障碍不仅仅是一些 CPU 指令。它是一个 合乎逻辑的 障碍,对 JIT 编译器也有影响。特别是,这意味着 JIT 编译器不会缓存或重新排序 x
相对于 v
的负载。
在JSR 133 Java Memory Model FAQ中,它表示
the new memory model places stricter constraints on reordering of volatile field accesses with other field accesses, volatile or not, anything that was visible to thread A when it writes to volatile field f becomes visible to thread B when it reads f
它还给出了如何使用可变字段的示例
class VolatileExample {
int x = 0;
volatile boolean v = false;
public void writer() {
x = 42;
v = true;
}
public void reader() {
if (v == true) {
//uses x - guaranteed to see 42.
}
}
}
在上面的代码中,JVM(JIT?)会在 v
的负载和 x
的负载之间插入一个 LoadLoad
内存 barrier/fence reader()
,指的是The JSR-133 Cookbook for Compiler Writers(实际实现取决于底层CPU架构)
并且硬件使用缓存一致性协议来确保 L1,2... 缓存和主内存之间的一致性。
但我猜想这些机制似乎不够充分。为了保证在 reader()
中看到 42
,JVM(JIT)是否必须从主内存(或 L1)读取 v
(非易失性)和 x
(易失性) ,2.. 由硬件控制的缓存)而不是 CPU 寄存器?
是否有任何链接或文档显示 JVM 如何实现新内存模型的详细信息? The JSR-133 Cookbook for Compiler Writers只展示了内存屏障是如何使用的,而没有提到缓存(在寄存器,L1,2..缓存,主内存中)。
LoadLoad
障碍不仅仅是一些 CPU 指令。它是一个 合乎逻辑的 障碍,对 JIT 编译器也有影响。特别是,这意味着 JIT 编译器不会缓存或重新排序 x
相对于 v
的负载。