locksupport通过park()和unpark(thread)实现线程挂起与唤醒,基于每个线程独有的许可(permit)机制:unpark设permit为1(不累积),park消耗permit或阻塞,支持先unpark后park、无需锁、可响应中断但不抛异常,需配合条件循环检查使用。

Java 中用 LockSupport 挂起和唤醒线程,核心是调用 park() 和 unpark(Thread) 方法。它不依赖对象监视器,也不需要 synchronized 或 wait/notify 的配合,底层基于 UNSAFE 的线程阻塞机制,更轻量、更灵活。
LockSupport.park():挂起当前线程
调用 LockSupport.park() 会让当前线程进入 WAITING 状态,直到被其他线程调用 unpark() 唤醒,或被中断。注意:
- 它不会释放任何锁(与 Object.wait() 不同);
- 如果目标线程已调用过 unpark()(许可已存在),那么 park() 会立即返回,不会阻塞;
- 可以带 blocker 参数用于诊断(如 JStack 显示阻塞原因)。
常见写法:
-
LockSupport.park();—— 无条件挂起 -
LockSupport.park("waiting for signal");—— 带诊断信息 -
LockSupport.parkUntil(System.currentTimeMillis() + 5000);—— 超时挂起 -
LockSupport.parkNanos(1_000_000L);—— 纳秒级超时挂起
LockSupport.unpark(Thread):唤醒指定线程
LockSupport.unpark(Thread thread) 会为指定线程发放一个“许可”(permit)。这个许可最多只有一个,多次调用 unpark() 效果等价于一次(即许可不可叠加)。关键点:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 唤醒操作可以发生在
park()之前——许可会被保存,后续park()直接消耗并返回; - 必须传入有效的
Thread对象(不能为 null); - 对已终止线程调用
unpark()无效,但不会报错。
示例:
Thread t = new Thread(() -> {
System.out.println("before park");
LockSupport.park();
System.out.println("after park");
});
t.start();
// 确保 t 已启动再 unpark
Thread.sleep(10);
LockSupport.unpark(t);
与 wait/notify 的关键区别
理解差异能避免误用:
-
wait()必须在 synchronized 块中调用,park()无需任何同步上下文; -
wait()会释放锁,park()不释放任何资源; -
notify()只能唤醒等待同一对象 monitor 的线程,unpark()可定向唤醒任意线程; -
wait()被中断会抛InterruptedException,park()被中断仅设置中断状态,需手动检查Thread.interrupted()。
实际使用注意事项
LockSupport 是 AQS(AbstractQueuedSynchronizer)的底层支撑,日常开发一般不直接使用,但在自定义同步器或高性能并发工具中很关键。使用时注意:
- 避免“丢失唤醒”:如果
unpark()先于park()执行,没问题;但如果逻辑顺序颠倒且没做状态校验,可能造成线程永远挂起; - 中断处理要显式判断:挂起后应检查
Thread.interrupted(),决定是否退出或重试; - 不要在循环中无条件
park(),通常配合条件变量或状态标志使用; - 调试时可通过
jstack查看线程堆栈,blocker 字符串会显示在 “parking to wait for” 行中。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










