公平锁与非公平锁的核心差异在于“抢锁前是否必须先排队”:公平锁强制线程先入队再按fifo顺序唤醒,避免饥饿但性能略低;非公平锁允许线程直接cas抢占,失败才排队,吞吐更高但可能导致饥饿。

公平锁和非公平锁的核心差异不在“能不能抢”,而在于“抢之前要不要先排队”。理解这一点,就能抓住它们在实现和性能上的关键分野。
公平锁:先登记,再等待,严格按序唤醒
公平锁的实现依赖 AQS(AbstractQueuedSynchronizer)中的双向同步队列。线程尝试获取锁时,哪怕锁此刻空闲,也会先检查队列是否为空;只要队列里有等待者,它就必须入队尾,老老实实排队。只有当它排到队首、且锁刚好释放时,才被唤醒并获得锁。
- 每次加锁都触发一次队列操作(入队 + CAS 设置状态),开销稳定但偏高
- 线程从运行态 → 阻塞态 → 唤醒态 → 运行态,涉及多次用户态/内核态切换
- 避免饥饿,适合对响应时间一致性要求高的场景(如金融交易指令调度)
非公平锁:先试抢,抢不到再排队
非公平锁在获取锁时会“插队”:它不查队列,直接用 CAS 尝试抢占锁。成功就立刻执行;失败才去检查队列——若队列为空或自己是第一个,仍可尝试自旋重试;否则才入队等待。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 减少了不必要的排队和上下文切换,尤其在低竞争或锁持有时间短时优势明显
- 存在“刚释放锁就被新来线程抢走”的情况,导致队列头部线程持续等待(即可能饥饿)
- synchronized 和 ReentrantLock 默认都是非公平的,这是 JVM 和并发包多年实测后的默认权衡
性能选择不能只看吞吐率,要看竞争模式
非公平锁吞吐更高,但不是万能解。实际选型要结合真实负载特征:
- 高并发、低延迟敏感、锁持有时间短(如计数器、简单状态更新)→ 非公平锁更稳
- 线程到达节奏高度不均、存在长尾等待风险(如后台批处理任务混合实时请求)→ 公平锁可防个别线程饿死
- 绝大多数业务场景下,非公平锁配合合理的锁粒度控制(比如只锁必要代码块),比强行用公平锁更能提升整体吞吐
ReentrantLock 的公平性是可配置的,synchronized 则不可切换
ReentrantLock 构造时传入 true 即启用公平模式:new ReentrantLock(true);而 synchronized 固定为非公平实现,且无法修改。这意味着:如果业务明确需要公平性,又必须用显式锁,ReentrantLock 是唯一选择;但也要意识到,开启公平模式后,它的平均获取延迟会上升,吞吐通常下降 20%~30%,需压测验证。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










