公平锁严格按等待顺序分配锁,非公平锁允许新线程抢占;前者吞吐低但保证FIFO,后者性能高但可能饥饿;tryLock()始终非公平;Synchronized默认非公平且不可配。

公平锁会严格按等待顺序分配锁,非公平锁允许插队
公平锁(ReentrantLock(true))让线程排队获取锁,先调用 lock() 的线程优先获得;非公平锁(ReentrantLock(false),也是默认构造)允许刚唤醒或新来的线程直接尝试抢占锁,哪怕队列里已有等待者。这不是“随机”,而是基于 CAS 快速抢锁的机制——只要当前锁空闲,就可能被新线程抢走。
非公平锁吞吐量更高,但可能引发线程饥饿
非公平锁减少线程挂起/唤醒开销,在高竞争场景下平均吞吐更高;公平锁因强制排队,上下文切换更频繁,性能通常低 10%–30%。但要注意:如果写线程持续高频抢锁,读线程可能长期得不到机会,尤其在单核或锁持有时间长的场景下,Thread.isInterrupted() 或超时机制也救不了它。
公平锁的 tryLock() 行为和非公平锁一致
无论是否公平,tryLock() 都是立即尝试、不排队、不阻塞。它底层调用的是非公平路径的 CAS 尝试,所以:
-
ReentrantLock(true).tryLock()仍可能跳过队首线程 - 想真正“按序尝试”,得用
tryLock(long, TimeUnit)配合自定义排队逻辑 - 公平性只体现在
lock()和条件队列唤醒上
实际选型:默认用非公平,仅当业务强依赖 FIFO 时才切公平
多数业务不需要绝对顺序,比如缓存更新、日志写入、计数器累加,非公平锁已足够健壮;只有类似资源池分配、任务调度队列、银行账户扣款等明确要求“先到先服务”的场景,才值得承担性能损失启用公平模式。另外注意:Synchronized 本质是非公平的,且不可配置。
立即学习“Java免费学习笔记(深入)”;
ReentrantLock fairLock = new ReentrantLock(true); // 公平 ReentrantLock unfairLock = new ReentrantLock(); // 非公平(等价于 new ReentrantLock(false))
公平性开关一旦创建就不能改,而且它只影响锁获取逻辑,不影响重入、条件变量或中断响应行为。最容易被忽略的是:即使开了公平锁,如果线程在 await() 后被唤醒,再调用 lock() 时仍要重新排队——不是“唤醒即得锁”。











