LockSupport 的 park/unpark 底层原理是每个线程私有、不可累积的二元许可(permit),初始为0;unpark 将目标线程 permit 置1(不叠加),park 消费当前线程 permit(为1则清零返回,为0则阻塞);全部委托 Unsafe native 方法实现,基于 futex 等系统原语,脱离 monitor 锁体系,支持信号预发与精准唤醒。

LockSupport 的 park 和 unpark 底层唤醒原理,核心在于每个线程内部维护的一个**不可累积的二元许可(permit)**,以及 JVM 层面对该许可的原子操作支持。
许可机制:线程自带的“一次有效开关”
每个 Java 线程在创建时,JVM 就为其隐式关联一个初始值为 0 的 permit。这个 permit 不是对象字段,也不属于 Java 层面可直接访问的变量,而是由 JVM 在线程结构体中维护的轻量状态:
- unpark(Thread t):将目标线程 t 的 permit 设为 1(若原值已是 1,则无变化);如果此时 t 正在 park 中阻塞,JVM 会立即唤醒它
- park():检查当前线程的 permit 值;若为 1,则立即将其设为 0 并返回(不挂起);若为 0,则线程进入阻塞态,等待 permit 变为 1
- permit 最多为 1,多次 unpark 同一线程等价于一次——不会叠加,也不会丢失,这是它比 wait/notify 更可靠的关键
底层实现:依赖 Unsafe.park 与 Unsafe.unpark
LockSupport 所有 park/unpark 方法最终都委托给 Unsafe 类的 native 方法:
-
Unsafe.park(boolean isAbsolute, long time):对应 park()、parkNanos()、parkUntil() -
Unsafe.unpark(Thread thread):向指定线程发送唤醒信号 - 这些 native 方法由 JVM 实现(如 HotSpot),在 Linux 上通常基于 futex(快速用户空间互斥锁)或 pthread_cond_signal 等系统级原语封装,确保低延迟、无锁、线程安全
唤醒不依赖锁对象,也不怕调用顺序颠倒
与 Object.wait/notify 必须配合 synchronized 使用不同,park/unpark 完全脱离 monitor 锁体系:
立即学习“Java免费学习笔记(深入)”;
- unpark 可以在 park 之前调用,permit 提前置 1,后续 park 直接消费并返回——不存在“信号丢失”
- 没有“持有锁才能唤醒”的限制,任意线程可对任意目标线程 unpark,唤醒目标精准可控
- park 返回后不自动重新获取任何锁,也无需检查中断标志之外的其他前置条件(但业务逻辑仍需自行校验状态)
为什么能支撑 AQS 等高级同步器?
AQS 队列中节点的挂起与唤醒,正是靠这一机制实现“按需阻塞、定向唤醒”:
- 线程入队失败后,调用 park() 自我挂起,不消耗 CPU
- 前驱节点释放锁时,通过 unpark(next) 精准唤醒后继节点
- 整个过程不涉及 synchronized 或 Lock 对象,避免锁竞争和死锁风险,也规避了 notify 随机唤醒的问题


















