tryacquireshared返回值语义严格:>0表示获取成功且需唤醒后续节点,=0表示获取成功但不唤醒,

tryAcquireShared 的返回值语义必须严格遵循约定
该方法由子类实现,不能直接调用或忽略其返回值含义。返回值不是布尔型,而是有明确业务语义的整数:
- 大于 0:当前线程获取共享锁成功,且剩余资源仍充足,需主动唤醒后续等待节点(如 CountDownLatch 中的 count > 0、Semaphore 中 permits > 0)
- 等于 0:当前线程获取成功,但资源刚好耗尽,不触发唤醒传播(例如某次 acquireShared 恰好用完最后一个 permit)
-
小于 0:获取失败,线程将被封装为
Node.SHARED类型节点加入同步队列,进入阻塞等待
注意:该方法内部必须自行完成状态检查(如 compareAndSetState)、权限校验、可重入逻辑(若适用),AQS 不参与具体判断。
tryReleaseShared 必须是线程安全的无锁操作
此方法在释放阶段被调用,设计上要求具备原子性与幂等性,典型场景是 CAS 循环更新状态值:
- 不能依赖锁或 synchronized 块,否则会引发死锁(释放锁时可能正持有其他锁)
- 推荐使用
compareAndSetState(expect, update)配合循环重试,确保状态变更可靠 - 返回 true 表示释放成功并应触发唤醒(如唤醒队列头后首个共享节点);返回 false 表示释放未生效,上层
releaseShared将不再继续传播唤醒
例如 Semaphore 的实现中,它尝试将 state 原子减 1;若减成功则返回 true,否则返回 false 并终止传播。
共享锁唤醒传播依赖“r >= 0”和 setHeadAndPropagate
当 tryAcquireShared 返回 ≥ 0 时,AQS 会执行 setHeadAndPropagate(node, r),这是共享模式区别于独占模式的关键:
- 先将当前节点设为新 head,再检查是否需要向后唤醒:不仅看当前
r > 0,还会判断后继节点是否为SHARED类型、以及后继节点前驱的 waitStatus 是否允许传播 - 唤醒不是简单 signal 一个节点,而是可能级联唤醒多个连续的共享节点(只要它们仍能成功 acquire)
- 子类无需手动唤醒,但必须保证
tryAcquireShared的返回值准确反映资源余量,否则传播链会提前中断
子类实现需隔离共享与独占逻辑,避免状态污染
AQS 内部 state 是单一整型字段,共享锁与独占锁共用同一 state,因此子类必须明确定义其语义划分:
- 如 ReentrantReadWriteLock 将 state 高 16 位用于读锁计数,低 16 位用于写锁重入次数
- Semaphore 直接将 state 视为可用许可数;CountDownLatch 则将 state 视为倒计数值
- 禁止在
tryAcquireShared中调用tryAcquire,也不应在tryAcquire中误判共享条件,否则导致行为错乱
状态解释权完全归属子类,AQS 只负责排队、挂起、唤醒等通用流程控制。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











