aqs共享模式中state语义因同步器而异:semaphore的state表示剩余许可数(越大越空闲),countdownlatch的state表示待完成任务数(越小越接近释放线程),该差异决定tryacquireshared返回逻辑及阻塞/放行时机。

看懂 AQS 共享模式的 state 含义是关键起点
两者都用 AbstractQueuedSynchronizer 的 state 字段存一个整数,但语义完全不同:Semaphore 的 state 是「剩余许可数」,越大表示越空闲;CountDownLatch 的 state 是「待完成任务数」,越小越接近释放等待线程。这个根本差异直接决定所有行为——比如 tryAcquireShared 返回值:Semaphore 返回负数表示“没许可了”,CountDownLatch 返回负数表示“计数还没到 0”。不厘清这点,看源码只会越看越乱。
tryAcquireShared 的返回逻辑决定阻塞/放行时机
这是共享模式下最核心的钩子方法,两者的实现路径截然不同:
-
Semaphore.NonfairSync.nonfairTryAcquireShared:用available - acquires计算剩余,若结果 -
CountDownLatch.Sync.tryAcquireShared:直接比较getState() == 0,等于 0 才返回 1(放行),否则返回 -1(阻塞)
注意:Semaphore 支持一次 acquire(3) 拿 3 个许可,而 CountDownLatch 的 await() 永远只关心“是否为 0”,不支持“等一半”。这也是为什么 Semaphore 能做限流,CountDownLatch 只能做一次性门控。
release 操作对 state 的修改方向相反
释放行为暴露了设计意图的对立性:
-
Semaphore.release()调用tryReleaseShared(releases),本质是state += releases—— 把许可还回池子 -
CountDownLatch.countDown()调用tryReleaseShared(1),本质是state -= 1—— 把计数往下减
这种加减方向的差异不是偶然:Semaphore 的许可是“资源池”,用完要归还;CountDownLatch 的计数是“倒计时”,走完即终止。这也解释了为什么 CountDownLatch 不可重置,而 Semaphore 的 release 可以反复调用甚至超额释放(只要没溢出)。
公平性开关只在 Semaphore 中生效,CountDownLatch 无此概念
Semaphore 构造时可传 fair = true,启用 FairSync,其 tryAcquireShared 会先检查同步队列是否有等待者,再决定是否让当前线程插队;而 CountDownLatch 根本没有公平/非公平变体——它的 await() 从不“争抢”,只“守候”,所有等待线程都在队列里安静排队,直到 state 归零被统一唤醒。所以你在 CountDownLatch 源码里找不到 FairSync 或任何与公平策略相关的分支。










