影响其他非易失性变量内存一致性的Java易失性变量
场景A A1。写入易失性变量 A2。刷新所有对主存的本地非易失性变量写入 场景B B1。从易失变量中读取 B2。将所有非易失性变量从主内存重新加载到本地内存影响其他非易失性变量内存一致性的Java易失性变量,java,synchronization,shared-memory,volatile,memory-corruption,Java,Synchronization,Shared Memory,Volatile,Memory Corruption,场景A A1。写入易失性变量 A2。刷新所有对主存的本地非易失性变量写入 场景B B1。从易失变量中读取 B2。将所有非易失性变量从主内存重新加载到本地内存 场景A和场景B是否是与volatile相关的正确行为 变量?或者场景A也包括B2,或者场景B 还包括A2 这些场景是原子的吗?还有别的事吗 在A1和A2之间?还是B1和B2 (使用Java 1.8/1.5+)实际规则是“对可变变量v的写入(§8.3.1.4)与任何线程对v的所有后续读取同步(其中“后续”根据同步顺序定义)。” 换句话说,
- 场景A和场景B是否是与volatile相关的正确行为 变量?或者场景A也包括B2,或者场景B 还包括A2李>
- 这些场景是原子的吗?还有别的事吗 在A1和A2之间?还是B1和B2
v
的写操作,一旦另一个线程在该写操作之后读取了v
,则该线程的读操作都是可见的
我不确定“冲洗到主管道”是理解这一点的必要方式。Java内存模型是根据发生在之前发生的情况记录的,并与之同步。我建议用这些术语来思考。从概念上讲,JVM可以省略某些“刷新”,如果它们不是承诺所必需的。实际规则是“对易失性变量v的写入(§8.3.1.4)与任何线程对v的所有后续读取同步(其中“后续”是根据同步顺序定义的)。”
换句话说,从一个线程到写入v
的写操作,一旦另一个线程在该写操作之后读取了v
,则该线程的读操作都是可见的
我不确定“冲洗到主管道”是理解这一点的必要方式。Java内存模型是根据“发生之前”和“与同步”来记录的。我建议用这些术语来思考。从概念上讲,JVM可以省略某些“刷新”,如果它们不是承诺所必需的。写入易失性变量并不保证刷新非易失性变量1。但是,它将在对volatile的写入和对volatile的任何后续读取之间引入一种“发生在”关系(假设没有对其进行中间写入)。您可以通过以下方式利用此漏洞:
synchronized
更简单、更健壮
你的例子不清楚:
- 如果它旨在描述Java程序员必须做的事情,那么它是错误的/荒谬的。Java代码无法刷新变量
- 如果它是一个必须在实现级别(例如在JIT编译的代码中)发生什么的规范,那么它也是错误的
- 如果它旨在描述在实现级别(例如在JIT编译的代码中)可能发生的情况,那么它是正确的
1-JLS不需要特定于硬件的操作,如刷新。相反,它要求编译后的代码满足某些特定的内存可见性保证,并将实现留给编译器编写器。写入易失性变量并不保证刷新非易失性变量1。但是,它将在对volatile的写入和对volatile的任何后续读取之间引入一种“发生在”关系(假设没有对其进行中间写入)。您可以通过以下方式利用此漏洞:
synchronized
更简单、更健壮
你的例子不清楚:
- 如果它旨在描述Java程序员必须做的事情,那么它是错误的/荒谬的。Java代码无法刷新变量
- 如果它是一个必须在实现级别(例如在JIT编译的代码中)发生什么的规范,那么它也是错误的
- 如果它旨在描述在实现级别(例如在JIT编译的代码中)可能发生的情况,那么它是正确的
1-JLS不需要特定于硬件的操作,如刷新。相反,它要求编译后的代码满足某些特定的内存可见性保证,并将实现交给编译器编写者。这是一个多么好的答案,简洁却透彻且可理解。这是一个多么好的答案,简洁却透彻且可理解。