在semaphore中,state表示剩余可用许可数;在countdownlatch中,state表示尚未完成的倒计数次数。两者均基于aqs,但语义不同,导致行为差异:semaphore支持acquire/release交错,countdownlatch仅单向递减且不可逆。

state 变量在 Semaphore 和 CountDownLatch 中分别代表什么
两者都基于 AQS,但 state 的语义完全不同:对 Semaphore 来说,state 是剩余可用的“许可数”;对 CountDownLatch 来说,state 是尚未完成的“倒计数次数”。这个区别直接决定了它们的行为边界——Semaphore 允许 acquire 和 release 交错发生,而 CountDownLatch 只能递减、不能重置,且一旦归零就不可逆。
tryAcquireShared 返回值为什么是 remaining 而不是 boolean
AQS 共享模式要求子类的 tryAcquireShared(int) 返回一个整数,用于指示获取结果:
- 返回值 ≥ 0:表示获取成功,且数值是“剩余资源量”,AQS 会继续唤醒后续共享节点;
- 返回值 Semaphore 的 nonfairTryAcquireShared 直接计算 available - acquires,并用 CAS 尝试更新 state;CountDownLatch 的 tryAcquireShared 则只检查 getState() == 0,等于 0 才返回 1(表示可通行),否则返回 -1(阻塞)。
release 操作为何不总触发唤醒,但 acquire 失败一定入队
这是共享锁的典型优化点:
- Semaphore.release() 会调用 releaseShared(1),最终执行 doReleaseShared() ——但它只在有等待线程且头结点状态合适时才尝试唤醒后继;
- CountDownLatch.countDown() 同样调用 releaseShared(1),但只有当 state 从 1 减到 0 的瞬间,才会触发一次性的全量唤醒(所有 await 中的线程);
- 关键差异在于:Semaphore 的每次 release 都可能“救活”一个等待者,而 CountDownLatch 的唤醒只发生在归零那一刻,之前的所有 countDown 都只是原子减法,不唤醒任何人。
公平性开关如何影响 state 的竞争逻辑
Semaphore 支持构造时传入 fair = true,此时 tryAcquireShared 会先调用 hasQueuedPredecessors() 判断队列中是否有更早等待的节点;若存在,直接返回 -1,强制当前线程入队,避免插队。而 CountDownLatch 不提供公平/非公平选项——它的 await() 本质是“等归零”,不存在“插队获取”的语义,所以无需区分。
真正容易被忽略的是:state 归零后,CountDownLatch 的 await() 立即返回,但 Semaphore 的 acquire() 即使发现 state > 0,仍需通过 CAS 确保扣减成功,否则要重试。这个 CAS 循环和是否公平无关,是共享资源安全分配的底层保障。










