You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中volatile的正确测试方式及不同平台运行结果差异原因

两种环境表现不同的核心原因

Java内存模型(JMM)只规定了多线程场景下可见性的最低要求,并没有禁止不同虚拟机实现提供比规范更强的可见性保障,你遇到的差异本质是桌面HotSpot JVM和Android ART虚拟机的JIT编译策略不同导致的。

桌面JVM(Eclipse运行环境)的表现原因

你在Eclipse里用的是标准OpenJDK/OracleJDK的HotSpot虚拟机,它的JIT编译器会做非常激进的优化:对于没有volatile、synchronized等同步修饰的共享变量,当JIT判断该变量不会被当前线程修改时,会把循环内的变量读取操作提升到循环外部,相当于把变量值缓存在寄存器里,后续循环运行时只会读取寄存器的缓存值,不会再同步主内存的最新更新,所以你看到reader线程只读到了第一次修改的1,后续更新都感知不到。

你可以做个简单验证:给Eclipse的运行参数加上-Xint强制关闭JIT、使用纯解释模式运行,你会发现reader线程也能读到所有num的更新,和Android上的表现一致。

Android ART虚拟机的表现原因

Android的ART虚拟机的JIT优化策略和桌面HotSpot差异很大,当前版本的ART不会对这种短生命周期的循环做这类激进的变量提升优化,reader线程每次读取num时都会访问共享内存,所以能拿到最新的值。

但要特别注意:这只是ART当前实现的额外特性,不是规范要求的保证。如果未来ART调整了JIT优化策略,或是你在其他版本的Android系统上运行,这段代码依然可能出现可见性问题。

补充提示

不要依赖特定虚拟机的实现细节编写代码,只要是多线程共享的可变变量,必须严格遵循JMM规范,添加volatile修饰或是使用同步机制保证可见性,否则代码的正确性是没有保障的。


内容的提问来源于stack exchange,提问作者BobTheCat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 20:54:04