aqs的interruptible获取机制通过在入队前检查中断状态并结合park后二次校验,确保线程能及时响应interrupt而抛出interruptedexception;其与acquire的根本区别在于是否捕获并处理中断信号。

AbstractQueuedSynchronizer(AQS)的 interruptible 获取机制,核心在于让线程在阻塞等待锁时,仍能及时感知并响应 Thread.interrupt(),而不是等到锁被释放后才抛出 InterruptedException。 这种设计避免了“假唤醒延迟响应”问题,是可中断同步器(如 ReentrantLock.lockInterruptibly()、CountDownLatch.await())可靠性的底层保障。
interruptible 获取的本质:进入队列前先检查中断状态
AQS 的可中断获取(如 acquireInterruptibly)不是在 park 之后再轮询中断,而是在每次尝试获取失败、准备挂起线程前,主动调用 Thread.interrupted() 检查当前是否已被中断。一旦发现已中断,立即抛出 InterruptedException,不入队、不 park。
- 这保证了中断信号不会被“吞掉”,也不依赖操作系统级的 park 唤醒时机
- 即使线程刚被 park,只要中断发生在 park 调用之前或 park 返回途中(JVM 保证 park 可被中断唤醒),AQS 都能捕获并处理
- 典型流程:尝试 acquire → 失败 → 检查中断 → 已中断?→ 是:抛异常;否:入 CLH 队列 → park
park 与中断的协同:Unsafe.park 的语义是关键
AQS 底层使用 LockSupport.park(this),而 park 本身对中断敏感:若线程在 park 中被中断,park 会立即返回,并自动清除中断状态(即 Thread.interrupted() 后续返回 false)。AQS 利用这一点,在 park 返回后再次检查中断状态(通过 Thread.interrupted())来判断是否因中断而醒。
- park 返回 ≠ 获取成功,必须重新 tryAcquire
- park 返回后若检测到中断(说明是被 interrupt 唤醒),则清理节点、抛出异常,不继续竞争
- 这种“park + 再检查”模式,是实现“响应及时性”和“语义正确性”的关键折中
与不可中断获取(acquire)的根本区别
acquire() 完全忽略中断:即使线程在等待中被 interrupt,它仍安静地留在队列中,直到前驱节点释放锁、自己被 unpark 并成功 acquire。中断状态会被 park 清除,且无人捕获处理。
-
acquireInterruptibly():中断 → 立即失败,清理资源,抛InterruptedException -
acquire():中断 → 无反应,继续等待,中断状态丢失(除非用户手动保存) - 二者共享同一套队列和 park/unpark 逻辑,差异仅体现在中断检查的插入位置和异常处理路径
实际使用中的注意事项
调用 interruptible 方法(如 lockInterruptibly())后,必须正确处理 InterruptedException:通常应恢复中断状态(Thread.currentThread().interrupt())或明确放弃操作,避免掩盖中断意图。
- 不要只 catch 了事,也不要在 finally 中无条件重置中断状态
- 若在 interruptible 等待期间发生中断,线程不会持有锁,也未改变同步状态,是安全的退出点
- 注意:中断不能强制释放他人持有的锁,只能让等待者提前退出等待










