Semaphore基于AQS的state变量实现许可计数,通过共享模式原子增减state控制并发线程数;公平性由FairSync/NonfairSync子类决定;state可为负或超初始值,属设计特性。

Semaphore 通过 AQS(AbstractQueuedSynchronizer)的 state 变量作为许可计数器,实现对并发线程数量的精确控制。它不是靠锁的“互斥”逻辑,而是靠共享模式下的原子状态变更和队列调度来达成限流目标。
state 就是许可总数
AQS 的核心是 volatile int state,Semaphore 在构造时就用它存初始许可数:
-
new Semaphore(5) → 调用
setState(5),state = 5 - 每次
acquire()成功 → state 原子减 1(AQS 的compareAndSetState保证) - 每次
release()成功 → state 原子加 1 - 当 state == 0 时,后续
acquire()会失败,触发线程入 AQS 同步等待队列
共享模式决定“多人可进”
不同于 ReentrantLock 使用 AQS 的独占模式(一次只放行一个线程),Semaphore 使用的是 共享模式:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
tryAcquireShared(int acquires)判断是否允许获取:若getState() >= acquires,就 CAS 减去 acquires 并返回非负值,表示成功 - 返回负值(如 -1)则线程被挂起,加入 AQS 的 FIFO 队列等待唤醒
- 有线程调用
release()时,会调用doReleaseShared()唤醒队列头部的等待线程
公平性由 Sync 子类控制
AQS 不直接处理公平逻辑,而是交由 Semaphore 内部的 Sync 实现:
立即学习“Java免费学习笔记(深入)”;
-
NonfairSync(默认):
tryAcquireShared不检查队列,新请求可能“插队”,吞吐高 - FairSync:先检查 AQS 队列是否为空,非空则拒绝当前请求,确保 FIFO 分配
- 两者都复用同一套 state 管理和队列唤醒机制,仅在“能否抢跑”上做区分
许可泄漏与负 state 是设计特性,不是 bug
AQS 允许 state 被减到负数,Semaphore 也继承了这一点:
- 多次
release()而未acquire()→ state 变成正数甚至很大,后续 acquire 会立刻成功 - 这在某些场景有用(如预占许可、补偿释放),但业务代码中应严格配对,避免掩盖竞争问题
- 可通过
availablePermits()监控实时许可数,结合日志或 Arthas 追踪异常波动

















