选公平还是非公平取决于业务对顺序与性能的权衡:公平模式严格FIFO、避免饥饿但吞吐低10%–25%,适合金融交易等顺序敏感场景;非公平模式允许插队、吞吐更高,但可能导致尾部线程饥饿,适用于缓存读取等短任务场景。

选公平还是非公平,关键不在“听起来更合理”,而在你系统里线程等许可时,能不能容忍有人插队、愿不愿意为顺序多花点调度成本。
公平模式:谁先来,谁先上
公平模式下,每个调用 acquire() 的线程都会被放进一个FIFO等待队列。释放许可时,只唤醒队首线程——不看新来的有没有力气抢,只看谁排队排得最久。
- 适合金融交易、日志落盘、审计操作等顺序敏感型任务,避免关键请求被持续延迟
- 能彻底规避线程饥饿,后启动的线程不会永远卡在队尾
- 代价是每次 acquire 都要检查队列状态,上下文切换略多,吞吐量通常比非公平低10%–25%
- 初始化写法:new Semaphore(5, true)
非公平模式:谁手快,谁先得
非公平模式默认开启。线程一来就直接尝试抢占:只要当前有空闲许可,哪怕队列里已有5个线程在等,它也能立刻拿走——不排队、不谦让。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 适用于缓存读取、静态资源服务、批量查询等响应快、容忍乱序的场景
- 减少线程阻塞和唤醒次数,平均获取延迟更低,高并发短任务下吞吐更高
- 风险是:如果总有新线程高频抵达,队列尾部的线程可能长期等不到许可(即线程饥饿)
- 初始化写法:new Semaphore(5) 或 new Semaphore(5, false)
怎么选?看三个信号
不用猜,盯住你系统的实际行为:
- 压测时平均等待时间是否稳定?波动大+尾部延迟飙升 → 考虑切公平
- 业务日志里有没有“某类请求总在超时边缘”?比如支付回调偶发积压 → 公平模式可缓解
- CPU利用率高但吞吐上不去?可能是锁竞争激烈+频繁上下文切换 → 非公平往往更轻量
实战中容易踩的坑
公平性只是机制起点,真正影响效果的是配套动作:
- 忘记在 finally 块里调用 release() → 许可永久泄漏,队列越积越长
- 许可数设得太小(如数据库连接池只配3个许可却跑50个线程)→ 公平也救不了排队地狱
- 混用两种模式做AB测试却不隔离线程池 → 结果不可比,因为线程调度上下文已污染
- 以为“公平=绝对准时” → 实际仍受JVM线程调度、GC停顿等干扰,只是相对更可预期

















