ReentrantReadWriteLock写锁释放后唤醒读节点的核心链路是sync.tryRelease()→unparkSuccessor()→doAcquireShared()→setHeadAndPropagate(),通过被唤醒读线程接力传播共享许可实现批量唤醒,而非调用不存在的signalNext方法。

ReentrantReadWriteLock 的写锁释放后唤醒等待读节点的过程,核心在于 sync.tryRelease() → sync.unparkSuccessor() → doAcquireShared() 的协作链路,而非直接调用 signalNext(该方法并不存在于 JDK 源码中,可能是对 acquireQueued 或 setHeadAndPropagate 中传播逻辑的误称)。
写锁释放触发共享模式唤醒
当持有写锁的线程调用 writeLock().unlock(),最终进入 Sync.tryRelease(int)。该方法判断当前线程是否为独占持有者、重入计数是否归零;若满足,则清空 exclusiveOwnerThread,返回 true。随后 release() 调用 unparkSuccessor(h) 尝试唤醒后继节点。
- 此时若队列头节点的后继是共享模式(
node.nextWaiter == Node.SHARED),则唤醒它; - 但更关键的是:写锁释放后,往往需要“传播”共享许可——即唤醒所有连续的 SHARED 节点,而不仅是一个;
- 这个传播逻辑不在
unparkSuccessor中完成,而是在被唤醒的读线程执行doAcquireShared()后,通过setHeadAndPropagate实现。
被唤醒读节点执行 doAcquireShared
刚被 unpark 的读线程从 LockSupport.park() 返回,进入 doAcquireShared() 的自旋循环。它会尝试调用 tryAcquireShared()(在 Sync 中实现),判断是否可获取读锁:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 检查写锁是否已被释放(
exclusiveCount(c) == 0); - 检查读锁重入或公平性策略是否允许当前线程获取;
- 若成功,设置新头节点,并调用
setHeadAndPropagate(node, r)。
setHeadAndPropagate 完成“唤醒传播”
这是真正实现“唤醒后续读节点”的关键步骤。它不仅设置当前节点为头,还会根据返回值 r(即 tryAcquireShared 的结果)决定是否继续唤醒后继:
立即学习“Java免费学习笔记(深入)”;
- 若
r >= 0(表示还有剩余共享许可),且后继节点是 SHARED 模式,则调用unparkSuccessor(s); - 注意:这里不是唤醒任意一个,而是唤醒
s(当前节点的 next),并依赖被唤醒者再次调用setHeadAndPropagate形成链式传播; - 该机制避免了写锁释放时遍历整个队列,而是由每个成功获取读锁的节点“接力”唤醒下一个,兼顾效率与公平。
为什么没有显式的 signalNext 方法?
JDK 的 AQS 实现中并无名为 signalNext 的公开或内部方法。开发者可能混淆了以下概念:
-
ConditionObject.signal()用于await()/signal()场景,不适用于 ReadWriteLock 的队列唤醒; - 实际唤醒动作由
unparkSuccessor和setHeadAndPropagate共同承担; - 读锁获取的“信号传递”本质是共享模式下的“传播(propagation)”,属于 AQS 的标准设计,不是条件变量意义上的 signal。

















