跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

LockSupport 工具类:解析 park() 与 unpark() 相比 wait/notify 更加灵活的执行许可(Permit)机制

LockSupport 的灵活性源于每个线程独享的二进制许可机制:unpark() 置 permit 为 1(可预存、不叠加),park() 消费 permit 后归零;无需同步块,唤醒精准到线程实例,中断时不重置状态。

LockSupport 的灵活性核心在于它的许可(Permit)机制——这不是一个抽象概念,而是一个真实存在的、每个线程独享的二进制状态(0 或 1)。它让阻塞与唤醒不再强依赖执行时序,也不绑定锁对象,从而突破了 wait/notify 的固有约束。

许可是“可预存”的,不丢不叠加unpark() 的本质是把目标线程的 permit 设为 1;park() 则尝试将 permit 减为 0 —— 若已是 0,就挂起等待。关键点在于:unpark() 可以在 park() 之前调用,许可会暂存,后续 park() 立即返回,不会阻塞连续两次 unpark() 对同一线程只生效一次,permit 不会变成 2,第二次调用被忽略park() 成功消费许可后,permit 归零;若未被消费,许可一直有效,直到被 park() 拿走或线程终止无需同步块,调用位置完全自由wait() 必须出现在 synchronized 块内,且锁对象必须与 wait() 调用对象一致,否则抛 IllegalMonitorStateException;park() 完全不检查锁状态:可以在任意方法、任意代码位置安全调用,包括静态上下文、无锁逻辑分支中没有“锁对象”概念,自然不存在“notify 锁错对象”或“wait 和 notify 不是同一把锁”的典型错误适合嵌入非面向对象结构的底层同步逻辑,比如 AQS 中的节点等待机制唤醒精准到线程实例,不靠运气notify() 随机唤醒一个 wait 线程,notifyAll() 则唤醒全部——两者都无参数,无法指定目标;unpark() 显式接收 Thread 对象:可以精确控制哪个线程该被唤醒,适用于一对一信号传递场景(如回调触发、任务完成通知)

避免虚假唤醒和竞争浪费:不需要 while 循环+条件重检(虽然仍建议做业务校验)

结合 Thread ID 或自定义标识,容易实现可追踪、可调试的线程协作流程中断处理更轻量,状态不被清空park() 在被中断时只是立即返回,线程中断状态保持为 true(Thread.interrupted() 仍返回 true);wait() 则不同:wait() 清除中断状态,并强制抛出 InterruptedException,迫使开发者必须捕获并处理park() 让中断成为一种可选信号,由上层逻辑决定是否响应、如何响应,更适合构建可中断但不崩溃的同步器配合 Thread.interrupted() 检查,能自然融入带超时、可取消的等待逻辑中

相关文章