信号量是一种并发权限管理机制,通过许可证计数器控制并发线程数,支持公平/非公平模式,基于AQS共享模式实现,适用于连接池、限流等场景。

信号量(Semaphore)不是锁,而是一种并发权限管理机制——它不关心“谁在用”,只管“还能不能用”。核心在于许可证(permit)的发放与回收,通过计数器动态控制同时可执行的线程数量,适用于资源池、限流、协作调度等场景。
许可证模型:资源可用性由计数器决定
信号量内部维护一个整型计数器(state),代表当前可用的许可证数量。这个值在构造时设定,例如 Semaphore sem = new Semaphore(3) 表示最多允许3个线程并发访问。
- acquire():尝试获取1个(或多个)许可证,计数器原子减1;若结果为负,线程进入阻塞队列等待
- release():归还1个(或多个)许可证,计数器原子加1,并唤醒等待队列中的线程
- 计数器本身不绑定线程身份,同一线程可多次 acquire(导致计数器为负),也可多次 release(需确保逻辑正确)
公平性选择:先到先得 vs 高吞吐抢占
是否启用公平模式,直接影响线程获取许可的顺序和系统行为特征:
- 构造时传入
true(如new Semaphore(5, true))启用公平模式:等待队列按 FIFO 排序,避免饥饿,但上下文切换开销略高 - 默认非公平模式:新线程可能插队成功,提升吞吐量,但存在个别线程长期等待的风险
- 公平性只影响阻塞线程的唤醒顺序,不影响 acquire/release 的原子性保障
底层依托:AQS 共享模式的稳定支撑
Java 中的 Semaphore 完全基于 AbstractQueuedSynchronizer(AQS)实现,其 state 字段直接映射许可证数量:
- 使用 AQS 的共享锁模式(Shared Mode),允许多个线程同时持有许可
- NonfairSync 和 FairSync 是两个内部同步器子类,分别封装非公平/公平的 tryAcquireShared 逻辑
- 所有 acquire/release 操作最终都转化为对 state 的 CAS 更新,保证线程安全
典型用途:从连接池到接口限流
信号量的价值在于“控量不锁线程”,常见落地场景包括:
- 数据库连接池:限制同时打开的连接数,防止 DB 连接耗尽
- HTTP 客户端并发控制:如 OkHttp 连接池中设置最大并发请求数
- 文件批量处理:控制同时读写磁盘的线程数,缓解 I/O 压力
- API 接口限流:配合定时重置(如每秒发放 N 个 permit),实现简单令牌桶效果

















