volatile不能保证原子性但确保可见性和禁止重排序,配合while循环自旋等待可实现无锁状态同步;必须用while而非if,推荐Java 9+的Thread.onSpinWait()优化能效。

volatile 本身不提供原子性,但能确保变量的可见性和禁止指令重排序,配合自旋等待(busy-waiting)可实现无锁、低开销的状态轮询同步,适用于等待时间短、竞争弱的场景。
volatile 保证状态变更对所有线程立即可见
自旋等待依赖反复读取某个共享状态变量(如 flag、done、ready),若该变量未用 volatile 修饰,线程可能一直读取自己工作内存中的旧值,导致无限循环。加上 volatile 后,每次读都从主内存获取最新值,写操作也立即刷新到主内存。
例如:
volatile boolean ready = false;while (!ready) { /* 自旋 */ }
一旦其他线程执行 ready = true;,当前线程下一次读就能看到 true,退出循环。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
必须搭配 while 循环 + volatile 读,不能用 if
单次 if 判断无法应对“写入发生在判断之后”的竞态:即使 ready 变为 true,当前线程已跳过检查就无法响应。只有持续轮询才能捕获状态变化。
正确写法:
- 用 while (!flag) { Thread.onSpinWait(); }(Java 9+ 推荐)
- 或简单 while (!flag);(注意 CPU 占用)
- 避免 if (!flag) { while (!flag); } —— 存在检查盲区
注意:volatile 不能替代 synchronized 或 CAS 做复合操作
自旋等待适合「等待某个布尔状态就绪」,但不适用于需要原子更新的场景。比如:
- ✅ 可以:volatile int count; + while (count == 0);
- ❌ 不行:count++; —— 读-改-写非原子,仍需 AtomicInteger 或锁
- ⚠️ 注意:volatile 写不阻止后续普通读写被重排序(仅禁止其与自身读写重排),复杂逻辑建议用 VarHandle 或 Unsafe 的 full fence 显式控制
进阶:结合 Thread.onSpinWait() 降低功耗
Java 9 引入 Thread.onSpinWait(),提示 CPU 当前处于自旋热点,可触发硬件级优化(如暂停流水线、降频)。它不改变语义,但提升能效:
while (!ready) {Thread.onSpinWait();
}
该方法开销极小,推荐在所有自旋循环中使用,尤其在高并发、多核环境下效果更明显。

















