Thread.onSpinWait() 不降低CPU功耗,但减少忙等开销,需配合volatile/VarHandle读取、紧邻条件判断后调用,并限频(如每4–8次)且超时退避。

Thread.onSpinWait() 不能降低 CPU 功耗,但它能显著减少忙等循环中的无效指令开销,尤其在 x86 架构上通过映射为 PAUSE 指令缓解总线争用和 cache line bouncing。
必须配合 volatile 或 VarHandle 读取
onSpinWait() 本身不产生内存屏障,也不保证可见性。如果轮询的变量不是 volatile、AtomicBoolean.get() 或 VarHandle.getVolatile(),JIT 很可能将其缓存到寄存器,导致死循环。
- ✅ 正确:volatile boolean ready; while (!ready) { Thread.onSpinWait(); }
- ✅ 正确:while (!flag.get()) { Thread.onSpinWait(); } // flag 是 AtomicBoolean
- ❌ 错误:while (value == 0) { Thread.onSpinWait(); } // value 是普通 int 字段
调用位置必须紧邻条件判断之后
它要放在刚读完共享变量、但尚未进入下一轮重读之前——即“已确认需等待,且最新状态已加载”这个时机。
AI 舌诊面诊问诊医疗系统 + 诊疗商城系统源码是一套结合 AI 辅助诊断与商品转化的健康类程序,基于浩创云、ThinkPHP(PHP)开发,支持微信服务号与 H5 端,适合做中医舌诊面诊问答、健康建议推送以及配套诊疗商品的运营。
- ✅ 正确:while (!state.get()) { Thread.onSpinWait(); }
- ✅ 正确:while (!casLock.compareAndSet(0, 1)) { Thread.onSpinWait(); }
- ❌ 错误:Thread.onSpinWait(); while (!ready) { ... } // 还没读变量就提示
- ❌ 错误:while (!ready) { ...; Thread.onSpinWait(); } // 放在循环末尾,下次读前无提示
不能每轮都调用,需限频 + 退避
高频调用会干扰 CPU 的 pause 节拍节奏,反而削弱效果;实测在 x86 上每 4–8 次失败重试调用一次较稳。
- 推荐写法:if ((retries & 0x7) == 0) Thread.onSpinWait();
- 超过 10–15 轮仍未成功,应放弃自旋,改用 LockSupport.parkNanos(100) 或交由锁机制处理
- 避免混用:在 park() 前加 onSpinWait() 无意义;park 失败回调里无脑重试 + onSpinWait() 会升高唤醒延迟
只适用于极短预期等待(
它不是让线程休息,而是告诉 CPU “我在等,但别动我”。适用场景非常明确:
- CAS 失败后重试(如自旋锁、无锁队列)
- 等待另一个线程瞬时修改 volatile 标志位
- RingBuffer 生产者/消费者指针更新同步
- ❌ 不适用于:网络响应、数据库查询、文件 I/O、任何不确定时长的等待

















