fullyrelease 方法的作用是 await() 前一次性释放当前线程持有的全部重入锁,确保线程安全进入条件队列;因 condition.await() 要求必须完全释放锁,否则其他线程无法获取锁并 signal,导致永久等待;reentrantlock 支持重入,需清零 state 才算彻底释放;其实现通过 tryrelease(原state) 归零同步状态,失败则抛 illegalmonitorstateexception;释放后线程入条件队列并 park;唤醒时通过 savedstate 恢复原始重入计数。

fullyRelease 方法的作用是在 await() 执行前,将当前线程持有的所有重入锁(即 ReentrantLock 的全部可重入计数)一次性完全释放,确保线程能安全进入等待状态,避免死锁或阻塞在条件队列中。
为什么 await 前必须完全释放锁?
调用 Condition.await() 时,线程必须先释放关联的锁,否则其他线程无法获取该锁并调用 signal() 唤醒它,造成永久等待。而 ReentrantLock 支持重入,一个线程可能已多次加锁(如 lock() 调用了 3 次),仅 unlock() 一次是不够的 —— 必须清空整个重入计数。
fullyRelease 是如何做到“一次性全释放”的?
该方法定义在 AQS 内部,接收当前持有锁的节点(Node),核心逻辑是:
- 调用
tryRelease(arg),其中arg是当前 state 的完整值(即总重入次数); -
ReentrantLock.Sync.tryRelease(int releases)会直接用getState() - releases将 state 归零; - 若释放失败(比如 state 不匹配,说明锁被篡改),抛出
IllegalMonitorStateException; - 成功后返回原 state 值,供后续恢复使用(唤醒时需按此值重新 acquire)。
释放后线程怎么挂起?
fullyRelease 成功后,当前线程会被构造成一个新的 Node,加入 Condition 的**条件队列(condition queue)**,然后调用 LockSupport.park() 阻塞。此时线程不再持有任何锁,但保留在条件队列中,等待 signal 触发转移至 AQS 同步队列。
唤醒时如何恢复重入状态?
当被 signal() 唤醒并转移到同步队列后,在 acquireQueued 流程中会调用 acquire(1) 尝试重新获取锁。注意:此时不是恢复原来的重入次数,而是按普通方式获取 —— 但 ReentrantLock 的公平/非公平策略决定了是否允许立即重入。真正恢复“重入数”的时机是在 await() 返回前,通过 acquireQueued(node, savedState) 中传入的 savedState(即 fullyRelease 返回的原始 state)来完成 —— 它会调用 tryAcquire(savedState),把重入计数一次性设回原值。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











