java - 关于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 变量的值,而不是在本地缓存它,我不认为这是真的。我对吗?
解决方案
推荐阅读
- python - 有效地为多个变量分配不同的值
- powershell - Powershell - 导出 Active Directory 中的所有空组和非空组
- c# - 导致多个事件触发的天蓝色函数绑定
- java-stream - Java 8 流收集器打破了 HashMap 插入语义?
- ruby-on-rails - 自动扩展数据库和连接池
- c# - 在 DataContractJsonSerializer.ReadObject(stream) 中序列化遇到意外字符“<”错误
- python - matplotlib: xaxis dates ValueError: format %y requires year >= 1900 on Windows
- java - 如何使用 Kotlin 迭代类组件
- java - 使用此问题中提供的数据创建递归 TreeView?
- node.js - 使用 TypeScript 组织 nodejs-express 项目代码的最佳方法是什么?