semaphore内部用aqs的volatile state字段表示可用许可数,初始化设为permits值;acquire()通过cas原子减1,release()原子加1;state为0时线程入队等待,全程无锁依赖cas保证线程安全。

Java 中 Semaphore 内部通过 AQS(AbstractQueuedSynchronizer)的 state 字段 来维护并发许可的计数器。
这个 state 是一个 volatile int,直接代表当前可用许可证(permits)的数量。所有对许可的获取与释放操作,本质上都是对 state 的原子性更新。
acquire()调用时,尝试将state减去请求的许可数(比如 1);
若减后结果 ≥ 0,表示获取成功,state更新完成;
若减后为负数,说明许可不足,当前线程会被挂起,加入 AQS 同步队列等待。release()调用时,直接将state加上释放的许可数(比如 1),并唤醒等待队列中可能阻塞的线程。
整个过程由 AQS 提供的 CAS(Compare-And-Swap)操作保障线程安全,无需额外加锁。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
关键细节
该计数器不是独立变量,而是复用 AQS 的核心状态字段 —— 这意味着 Semaphore 的实现轻量、高效,且与 ReentrantLock、CountDownLatch 等共享同一套同步基础设施。
公平性如何影响计数器行为?
公平性不改变计数器本身的逻辑,只影响线程获取许可的顺序:
- 非公平模式(默认):新线程可直接尝试 CAS 修改 `state`,可能“插队”已排队线程
- 公平模式:线程必须先检查同步队列是否有等待者;若有,则放弃抢夺,主动入队,严格按 FIFO 分配许可
计数器可以为负数吗?
可以,但仅在中间计算过程中短暂出现(如 `acquire(5)` 时 `state=2`,则 `2−5 = −3`),此时获取失败,线程阻塞。实际存储的 `state` 值始终为非负整数 —— 因为只有获取成功或释放操作才会真正写回 `state`。
初始化时的计数器值
构造 `Semaphore(n)` 时,AQS 的 `state` 就被设为 `n`;传入 `0` 表示初始无许可,所有 `acquire()` 都会阻塞,直到有线程调用 `release()`。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










