Java中通过ReentrantLock(true)启用公平锁,它基于AQS的FIFO队列按请求顺序排队,避免饥饿但性能降低10%~30%,需配对使用lock()/unlock()并置于try-finally中。

Java 中通过 ReentrantLock 构造函数传入 true 即可启用公平锁,它会按线程请求锁的顺序排队,避免饥饿问题。
公平锁的创建方式
默认情况下 ReentrantLock 是非公平锁,要开启公平排队机制,需显式指定构造参数:
-
ReentrantLock lock = new ReentrantLock(true);——true表示启用公平策略 - 公平锁内部使用 FIFO 队列(AQS 的 CLH 队列)维护等待线程顺序
- 每次有线程尝试获取锁时,若锁空闲且队列为空,才允许直接抢占;否则必须入队等待
公平锁的排队行为特点
公平锁会严格遵循“先来后到”,但要注意它不保证 CPU 调度顺序,只保证 AQS 队列中的获取顺序:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 线程调用
lock()时,若锁已被占用,会被封装为节点加入同步队列尾部 - 当持有锁的线程释放锁(
unlock()),队首线程被唤醒并尝试获取锁 - 即使有新线程刚好在释放锁瞬间调用
lock(),也不会插队,必须排到队尾
实际使用中的关键注意事项
公平锁虽能避免饥饿,但性能开销比非公平锁大,使用前需权衡:
立即学习“Java免费学习笔记(深入)”;
- 每次加锁都要检查队列状态、插入节点、唤醒操作,吞吐量通常低 10%~30%
- 务必配对使用
lock()和unlock(),建议放在try-finally块中 - 示例写法:
lock.lock();<br>try {<br> // 临界区代码<br>} finally {<br> lock.unlock();<br>}
验证公平性的小技巧
可通过多线程竞争 + 日志观察排队效果:
- 启动多个线程循环调用
lock(),并在获取锁后打印线程名和序号 - 若输出呈现严格递增的获取顺序(如 T1→T2→T3→T1…),说明公平机制生效
- 对比非公平锁,后者常出现“后来者先得”的现象(比如刚释放锁就被新线程抢到)

















