AQS中断时仅将节点waitStatus设为CANCELLED,不释放锁、不修改state;唤醒时自动跳过取消节点,通过逻辑隔离和引用置空实现惰性清理与GC回收。

取消节点只标记不释放,锁状态完全不受影响
当线程在 doAcquireInterruptibly 中被中断而退出等待时,AQS 不会释放锁、不修改 state、也不调用 tryRelease。它只做一件事:把当前线程对应的 Node 的 waitStatus 设为 CANCELLED(值为 1)。这个标记是清理的起点,表示该节点已失效,后续唤醒逻辑会跳过它。
队列清理靠“逻辑跳过”,不是物理删除
AQS 不会在中断发生时立即从链表中物理移除节点,而是采用“惰性跳过”策略:
-
唤醒时自动绕过:
unparkSuccessor在找下一个有效后继时,会从head.next开始向后扫描,跳过所有waitStatus == CANCELLED的节点,直到找到第一个非取消节点。 -
入队时轻量清理:在
enq或shouldParkAfterFailedAcquire中,也会顺带跳过前驱为CANCELLED的节点,尝试用 CAS 更新前驱的next指针指向其后继。 -
传播式唤醒兜底:若前驱已取消或 CAS 更新失败,
cancelAcquire会触发一次unparkSuccessor,确保后继能被及时唤醒,避免阻塞。
节点引用断开后由 JVM 自动回收
一个 Node 被标记为 CANCELLED 并被前后节点逻辑隔离后,只要它不再被任何活跃对象引用,就满足垃圾回收条件:
-
Node.thread字段在节点取消后通常会被设为null(cancelAcquire中执行),切断对线程的强引用。 -
prev和next指针在清理过程中可能被更新,使其脱离双向链表主干路径。 - 没有其他静态或长生命周期对象持有该节点引用时,GC 可在下一次可达性分析中将其回收。
不依赖 finalize 或 Cleaner,纯基于引用可达性
AQS 的节点清理不使用任何特殊回收机制:
- 不注册
Cleaner,也不重写finalize方法。 - 不维护额外的弱引用/虚引用队列。
- 完全依靠 Java 垃圾回收器的标准可达性分析——只要节点不可达,就会被回收。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











