首页 > 解决方案 > 关于Java volatile字段可见性的问题

问题描述

我刚刚开始学习 java 多线程,并且经常被关键字 volatile 所困扰。

许多教程都在讨论 volatile 字段的可见性,就像“在对它的写操作完成后,所有读者(特别是其他线程)都可以看到 volatile 字段”。我怀疑字段上的完整写入如何对其他线程(或 CPUS)不可见(忽略某些编译器优化可能使程序无法在真实字段上读取的情况)?

据我了解,完成写入意味着您已成功将文件写回缓存,并且根据 MESI,如果该文件已被所有其他线程缓存,则所有其他线程都应该具有无效的缓存行。一个例外(由于我对硬核不是很熟悉,这只是一个猜想)可能结果会被写回寄存器而不是缓存,我不知道在这种情况下是否有一些协议可以保持一致性或 volatile 使其不写入以在 java 中注册。

在某些看起来像“隐形”的情况下会发生示例:

A=0,B=0; 
thread1{A=1; B=2;}  
thread2{if(B==2) {A may be 0 here}}

假设编译器没有对其进行重新排序,我们在 thread2 中看到的原因是由于存储缓冲区,我不认为存储缓冲区中的写入操作意味着完成写入。由于存储缓冲区和无效队列策略,这使得对变量 A 的写入看起来不可见,但实际上在 thread2 读取 A 时写入操作尚未完成。即使我们使字段 B 易失性,而我们将字段 B 的写入操作设置为带有内存屏障的存储缓冲区,线程 2 可以读取 0 的 b 值并完成。至于我, volatile 看起来与它声明的文件的可见性无关,

顺便说一句,由于我不是母语人士,我看过可能用我的母语的教程(还有一些英文教程)说 volatile 会指示 JVM 线程从主内存中读取 volatile 变量的值,而不是在本地缓存它,我不认为这是真的。我对吗?

标签: javamultithreadingvisibilityvolatile

解决方案


推荐阅读