启用公平锁需显式构造reentrantlock(true),但公平性仅在排队竞争时生效,要求临界区短且确定、避免trylock轮询、确保unlock在finally中执行,并通过getqueuelength()验证真实排队。

直接在构造时传 true 即可启用公平模式:new ReentrantLock(true)。但这只是必要条件,不是充分条件——光靠这个参数本身,并不能自动保证“先到先得”的实际效果,必须配合正确的使用方式和代码结构。
必须显式创建公平锁实例
ReentrantLock 默认是非公平的,不写参数或写 false 都等价于非公平锁。要启用公平策略,必须明确指定:
private final ReentrantLock lock = new ReentrantLock(true);- 不能在运行时修改:构造后无法切换公平性,
sync字段已绑定为FairSync,反射强行修改属于未定义行为,极易出错
公平性只在排队竞争时生效
公平锁的“先到先得”有前提:线程必须真正进入等待队列。它不阻止刚释放锁的瞬间被新线程抢到(这点和非公平锁一样),但后续所有排队请求会严格按 FIFO 顺序唤醒。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 如果某个线程持锁时间很长(比如做了 IO 或远程调用),其他线程哪怕排在队首,也得等它执行完
- 若业务中大量使用
tryLock()轮询,线程可能根本不进队列,公平性就无从谈起
临界区必须短且确定
公平锁只管调度顺序,不管执行效率。一旦临界区内耗时严重或不可控,就会让“先到”变成“白等”:
- 避免在
lock()后做网络请求、文件读写、大循环等操作 - 确保
unlock()一定放在finally块中,否则锁永远不释放,后续所有线程都会饿死 - 检查是否误用了多个锁实例(如每个对象 new 一把锁),导致根本没有共享竞争关系
验证是否真正在排队
可通过 getQueueLength() 和 hasQueuedThreads() 实时观察等待队列状态,确认线程确实在排队而非反复抢锁失败后立即重试:
- 持续增长的
getQueueLength()值说明线程在真实排队 - 若该值长期为 0,但仍有线程长时间等待,大概率是没进队(例如用了
tryLock()且没控制重试间隔)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










