LockSupport 是基于许可模型的轻量级线程阻塞工具,无需 synchronized 和监视器,unpark 提前调用不会丢失信号,park/unpark 可解耦调用且避免虚假唤醒问题。

LockSupport 是 Java 并发包中一个底层、轻量级的线程阻塞与唤醒工具,它绕开了 wait/notify 所依赖的“对象监视器(monitor)”机制,无需 synchronized 块或共享锁对象,也不用担心 notify 早于 wait 导致的丢失信号问题。它的核心是基于“许可(permit)”模型:每个线程都有一个隐式的 permit,park() 消耗它(若无则阻塞),unpark(Thread) 添加它(最多一个,重复调用只保留一次)。
用 park/unpark 替代 wait/notify 的基本模式
传统 wait/notify 要求必须在 synchronized 块内调用,且需明确指定同一对象作为监视器;而 LockSupport 完全解耦:
-
LockSupport.park()可在任意上下文调用,线程会阻塞直到收到许可或被中断 -
LockSupport.unpark(thread)可由任意线程调用,向目标线程发放一个许可(即使目标尚未 park,也不会丢失) - 不需要共享锁对象,也不用处理 IllegalMonitorStateException
- 没有“虚假唤醒”概念(但 park 仍可能因中断返回,需检查条件)
避免“信号丢失”的关键优势
wait/notify 中,如果 notify() 在 wait() 之前执行,信号就丢了;而 unpark() 发放的 permit 是“累积型”的(虽然最多存一个):
- 线程 A 先调用
LockSupport.unpark(B),B 尚未 park → permit 已就绪 - 之后 B 调用
LockSupport.park()→ 立即消费 permit,不阻塞 - 这天然解决了 notify 早于 wait 的经典竞态问题
配合状态变量实现安全等待(推荐用法)
尽管 park/unpark 更灵活,但仍需手动维护同步逻辑。典型做法是用 volatile 状态变量 + 循环检查:
立即学习“Java免费学习笔记(深入)”;
// 示例:简单的一次性信号量
volatile boolean ready = false;
// 生产者线程
ready = true;
LockSupport.unpark(workerThread);
// 消费者线程
while (!ready) {
LockSupport.park(); // 可被中断,建议加中断检查
}
// 继续执行...
注意:park() 不响应 volatile 变量变化,所以必须显式循环判断条件;同时应结合 Thread.interrupted() 处理中断。
实际应用中的注意事项
- 不要对已终止线程调用
unpark()(无效,但不报错) -
park()可能因中断、超时或虚假唤醒返回,务必配合条件变量重检 - 它不提供内存可见性保证 —— volatile 或显式同步仍需用于共享状态读写
- AQS(AbstractQueuedSynchronizer)等高级同步器内部大量使用 LockSupport,它是构建锁和条件队列的基石



















