LockSupport.parkNanos精度名义为纳秒,实则受OS调度限制,唤醒延迟通常为几至几十微秒;它不释放锁、不抛中断异常、可自主处理中断,适合AQS等低延迟场景,但须配合unpark或超时逻辑使用。

LockSupport.parkNanos 的精度本质是纳秒,但实际调度受 OS 限制
很多人看到 parkNanos(long nanos) 参数类型是 long 就默认它能精确到纳秒——这是误解。JVM 层面接收纳秒单位,但底层依赖操作系统的线程调度器(如 Linux 的 CFS),真实唤醒延迟通常在几微秒到几十微秒量级,和 Thread.sleep 处于同一调度层级,并不“更高精度”。真正区别在于:它不释放监视器锁、不抛 InterruptedException、无需同步块。
为什么 parkNanos 比 sleep 更适合某些低延迟场景
Thread.sleep 在挂起前会检查中断状态并立即抛出 InterruptedException;而 parkNanos 被中断时只是提前返回,Thread.interrupted() 才清中断标志——这让你能自主决定是否响应中断,避免意外退出等待逻辑。
- 适用于自旋+阻塞混合策略(如 AQS 中的 acquireQueued)
- 不会因中断导致状态机错乱(比如你正在等一个 volatile 标志位,中断不该终止等待)
- 无 synchronized 开销,避免锁竞争干扰计时
正确用法:必须配合 unpark 或超时逻辑,否则可能永久挂起
parkNanos 和 park() 一样,依赖许可证机制。如果目标线程从未被 unpark,且超时时间设为 0 或负数,它会退化为无期限阻塞(等价于 park())。常见错误写法:
LockSupport.parkNanos(1000); // 1000 纳秒 ≈ 1 微秒?实际几乎不可能执行完就唤醒
更合理的做法是结合循环与状态判断:
long deadline = System.nanoTime() + TimeUnit.MICROSECONDS.toNanos(5);
while (System.nanoTime() < deadline && !ready.get()) {
LockSupport.parkNanos(TimeUnit.MICROSECONDS.toNanos(1));
}
注意:TimeUnit.MICROSECONDS.toNanos(1) 返回 1000,不是 1——纳秒单位不能直接传 1。
容易被忽略的关键点:parkNanos 不改变线程中断状态
调用 parkNanos 后若被中断,方法返回,但 Thread.currentThread().isInterrupted() 仍为 true,且不会清标志。如果你后续还要调用 sleep 或 wait,它们会立刻抛异常。务必手动处理:
- 用
Thread.interrupted()清除并检测(推荐) - 或显式捕获后重置:
Thread.currentThread().interrupt();
这点和 sleep 行为差异极大,漏掉会导致诡异的中断传播问题。

















