Semaphore 不支持锁降级,其本质是基于许可计数的限流工具,无读写锁区分;它通过 CAS 操作 state 计数器实现 acquire/release,不记录持有线程、不保障锁状态转换,真正需要锁降级应使用 ReentrantReadWriteLock。

Java 中 Semaphore 本身不支持锁降级,它没有“读锁/写锁”之分,也不存在“降级”概念。所谓“Semaphore 锁降级”,是常见误解——把 ReentrantReadWriteLock 的锁降级机制错误迁移到了 Semaphore 上。二者底层模型、设计目标和使用契约完全不同。
Semaphore 的核心是许可计数,不是锁状态转换
Semaphore 控制的是“能否拿到 permit”,而非“持有某种锁”。它的 state 就是一个整型计数器,代表当前可用许可数量:
- acquire() → CAS 尝试将 state 减 1;失败则入 AQS 队列挂起
- release() → CAS 将 state 加 1,并唤醒等待线程
- 全程无“锁升级/降级”路径,也不涉及线程对同一资源的多重访问权限切换
- 它不记录哪个线程持有了 permit,更不支持一个线程“先写后读”的语义保障
资源释放必须严格配对,否则导致许可泄漏
Semaphore 的限流效果完全依赖 acquire/release 的成对调用。释放逻辑的关键在于:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- release() 不要求调用线程此前已 acquire —— 它可以无条件增加许可数(比如用于动态扩容)
- 但业务代码中,必须在 finally 块中 release,否则一旦异常跳出,permit 永久丢失
- 漏 release 的后果不是“性能下降”,而是整个信号量逐渐枯竭,后续线程永久阻塞
- 这不是 bug,而是契约:acquire 是申请,release 是归还,就像借书还书,不还就影响他人
真正需要锁降级的场景,该用 ReadWriteLock
当业务需要“修改后立即安全读取自己刚写的数据,且期间排斥其他写操作”,这是典型的锁降级需求:
立即学习“Java免费学习笔记(深入)”;
- 先 lockWrite() → 写数据
- 再 lockRead() → 当前线程可直接获取读锁(因写锁持有者特权)
- 最后 unlockWrite() → 只剩读锁,其他读线程可并发进入
- 这个过程保证了写后读的原子性和可见性,Semaphore 无法提供此类语义
混淆来源:公平性设置被误读为“降级策略”
有人把 Semaphore 构造时传入 true(公平模式)理解为“降级”,其实是误解:
- 公平模式只是让 acquire 线程严格按队列顺序获取 permit,避免新线程插队
- 非公平模式允许“抢”,吞吐高但可能饿死长等待线程
- 这属于调度策略差异,与锁的状态转换(如写→读)毫无关系

















