Semaphore信号量限流的核心逻辑是通过控制同时执行的线程数来防止资源过载,本质是并发数控制而非速率控制,适用于数据库连接池、下游接口等资源敏感场景,需确保acquire与release成对出现,并支持公平性选择、动态监控与弹性调整。

Semaphore 信号量限流的核心逻辑,是通过控制“同时执行的线程数”来防止资源过载,从而提升系统可用性。它不统计时间窗口内的请求数(如 QPS),而是直接限制并发访问深度——适合保护数据库连接池、下游接口、文件下载等资源敏感型操作。
限流目标明确:按并发数而非请求频次
信号量限流本质是并发数控制,不是速率控制。比如设置 new Semaphore(5),就表示最多 5 个线程能同时进入临界区;第 6 个线程会阻塞或失败,直到有线程释放许可。这种机制天然适配资源容量固定场景:
- 数据库连接池最大连接数为 20,每台应用实例配
Semaphore(20 / 实例数) - 调用外部保险核心系统,对方仅支持 30 并发,集群共 6 台机器 → 每台设
Semaphore(5) - 批量导出服务占用大量内存,限制同时运行任务不超过 3 个
关键代码结构:acquire + try-finally + release
必须确保许可获取与释放成对出现,否则会导致许可泄漏、限流失效。推荐使用 tryAcquire() 配合超时和降级,避免线程无限等待:
- 用
semaphore.tryAcquire(1, 100, TimeUnit.MILLISECONDS)设定获取许可的最长等待时间 - 获取失败时快速返回错误码、走缓存或返回默认值,不阻塞主线程
-
release()必须放在finally块中,即使业务逻辑抛异常也能归还许可 - 避免在异步回调或线程池子线程中忘记
release(),建议封装成工具方法统一管理
公平性与性能权衡:根据场景选模式
构造时可指定是否启用公平模式:new Semaphore(10, true) 表示 FIFO 分配,避免饥饿但吞吐略低;默认非公平模式响应更快,适合突发流量:
- 内部系统调用、延迟敏感型接口 → 用非公平模式(默认)
- 定时批处理任务、需严格顺序的资源调度 → 考虑公平模式
- 注意:公平模式不能完全消除饥饿,只是降低概率;高并发下仍建议配合熔断/排队策略
动态监控与弹性调整:让限流可观察、可运维
生产环境中,仅靠静态配置不够。需暴露关键指标并支持运行时调整:
- 定期采集
semaphore.availablePermits(),结合请求成功率、平均耗时做告警 - 通过 JMX 或 Actuator 端点暴露当前可用许可数、等待线程数
- 支持动态调用
semaphore.release(n)增加许可(需先有闲置许可)或reducePermits(n)主动收缩容量 - 灰度发布时,可按机器分组逐步调整 permit 数,验证系统水位变化

















