Semaphore的公平与非公平模式差异在于获取许可前是否检查等待队列顺序:公平模式严格FIFO,每次获取前调用hasQueuedPredecessors()确保不插队;非公平模式直接CAS竞争,允许新线程插队。释放逻辑两者完全一致。

Semaphore 通过 AQS 的共享模式实现许可控制,公平与非公平的关键差异在于 获取许可前是否检查等待队列顺序,而非“谁先到谁先得”的表面理解。底层都复用 AQS 的 state 字段(volatile int)表示剩余许可数,所有修改均靠 CAS 保证原子性。
公平模式:严格 FIFO 入队 + 前驱检查
使用 FairSync,其 tryAcquireShared 方法在每次尝试获取前调用 hasQueuedPredecessors():
- 若返回 true(队列中已有更早等待的线程),直接失败,当前线程必须入队尾
- 仅当队列为空或自己是队首时,才执行 CAS 尝试扣减 state
- 即使此刻许可充足,也绝不跳过排队中的线程——这是“公平”的全部含义
非公平模式:无条件竞争 + 自旋重试
使用 NonfairSync,核心是 nonfairTryAcquireShared 方法:
- 不查队列,直接读取当前 state,计算剩余许可(
available - acquires) - 若足够,立即 CAS 更新;失败则继续自旋,不主动让出 CPU
- 只有 CAS 多次失败后,才被动入队——新线程可能“插队”成功,老线程长期等待
释放许可:两者完全一致
release() 调用的是统一的 tryReleaseShared:
立即学习“Java免费学习笔记(深入)”;
- CAS 增加 state(即归还许可)
- 成功后唤醒 AQS 同步队列头节点线程(FIFO 顺序)
- 唤醒逻辑与获取模式无关,确保释放行为本身不引入不公平
构造与选择:默认非公平,显式开启公平
实例化时决定模式:
-
new Semaphore(5)→NonfairSync,吞吐优先 -
new Semaphore(5, true)→FairSync,响应可预测 - 注意:公平性只约束“获取”路径,不影响释放、超时或中断等其他行为


















