Semaphore基于AQS实现,以state字段直接表示剩余许可数:构造时设初值,acquire()使state减1(负则入队),release()使state加1并唤醒头节点;采用共享模式,通过tryAcquireShared判断获取是否成功。

Semaphore 内部通过继承 AQS(AbstractQueuedSynchronizer)并复用其队列管理与状态控制机制,实现许可的获取、释放和线程阻塞/唤醒。它不依赖线程绑定,而是纯粹靠 state 字段表示剩余许可数,所有同步逻辑围绕这个整型状态展开。
state 直接代表 permits 数量
AQS 的 state 字段在 Semaphore 中被直接用作可用许可计数器:
- 构造时调用
setState(permits),初始值即为总许可数 -
acquire()对应state -= 1;若减后为负,说明无许可可用,当前线程入队等待 -
release()对应state += 1;释放后立即尝试唤醒队列头部等待线程 - 整个过程不记录持有线程(区别于 ReentrantLock),任意线程都可 release
共享式获取逻辑走 tryAcquireShared
Semaphore 使用 AQS 的共享模式(shared mode),核心是重写 tryAcquireShared(int):
- 该方法返回值决定是否获取成功:≥0 表示成功,
- 内部用 CAS 原子更新
state,避免竞态;失败则进入 AQS 的doAcquireSharedInterruptibly流程 - 等待线程被封装为 Node 加入 CLH 同步队列,挂起前会检查前驱节点状态,确保唤醒链可靠
公平性由 Sync 子类控制
Semaphore 提供公平与非公平两种策略,体现在 tryAcquireShared 的具体实现中:
立即学习“Java免费学习笔记(深入)”;
- 非公平模式(默认):直接尝试 CAS 获取许可,不查队列,可能“插队”
- 公平模式:先调用
hasQueuedPredecessors(),若队列非空则放弃抢锁,老老实实排队 - 两者共用同一套 state 管理和队列唤醒逻辑,仅在“能否抢先尝试”上存在差异
释放操作触发级联唤醒
release() 最终调用 tryReleaseShared():
- 原子地将
state加 1 - 返回 true 后,AQS 自动调用
doReleaseShared(),从队列头开始唤醒一个或多个等待线程 - 由于是共享模式,唤醒后这些线程会再次调用
tryAcquireShared竞争许可,形成“释放→唤醒→再竞争”循环


















