java中reentrantlock的公平锁通过构造时传入true启用,基于aqs的clh队列实现fifo排队,确保“谁先排队、谁先执行”,适用于防饥饿和强顺序场景,但吞吐量低20%–30%。

Java 中用 ReentrantLock 的公平锁特性来保证任务执行顺序,核心是启用公平模式并配合正确的加锁/释放逻辑。它不改变线程调度本身,但能确保“谁先排队、谁先执行”这一逻辑顺序,对资源分配类、防饥饿场景很实用。
启用公平锁必须显式传参 true
默认的 ReentrantLock() 是非公平锁,线程可能插队获取锁。要启用公平策略,必须在构造时传入 true:
-
ReentrantLock lock = new ReentrantLock(true);✅ 公平模式,按请求顺序排队 -
ReentrantLock lock = new ReentrantLock();❌ 非公平模式,吞吐高但顺序不可控
这个参数只在初始化时生效,后续无法动态切换。
公平锁靠 AQS 的 CLH 队列实现 FIFO 调度
公平锁内部使用 AbstractQueuedSynchronizer(AQS)维护一个双向等待队列(CLH 变种)。关键行为包括:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 线程调用
lock()时,先检查队列是否为空;若非空,或自己不是队首,就直接入队尾,不抢锁 - 锁释放后,只唤醒队列头部节点,严格按入队先后顺序授予锁
- 即使锁刚释放、当前无竞争,新线程也不会跳过队列直接获取——这是“不插队”的根本保障
实际使用中要注意三点
公平锁不是“万能时序器”,需结合编码习惯才能稳定生效:
- 必须在 finally 块中 unlock:避免因异常导致锁未释放,阻塞整个队列
- 不要混用多种锁机制:公平锁只约束同一把锁的等待线程;若任务涉及多把锁或 synchronized,整体顺序无法保证
- 性能代价真实存在:每次加锁都要检查队列状态、CAS 更新指针,吞吐量通常比非公平锁低 20%–30%,高并发下上下文切换也更多
适合用公平锁的典型场景
不是所有排队需求都该上公平锁,以下情况更匹配:
- 资源有限且需严格轮询分配,比如数据库连接池、打印机任务队列
- 业务逻辑依赖“先提交先处理”,如订单扣减、积分发放等强一致性操作
- 存在明显饥饿风险,比如后台监控线程长期被高频请求线程压制
如果只是希望大致有序、更看重响应速度,非公平锁仍是默认推荐选择。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










