公平锁与非公平锁的核心区别在于tryAcquire中是否检查等待队列:公平锁调用hasQueuedPredecessors()判断是否排队,非公平锁直接CAS抢锁;两者lock()入口一致,重入逻辑相同,仅构造方式决定类型。

核心区别在 tryAcquire 方法中是否检查等待队列——公平锁多一次 hasQueuedPredecessors() 判断,非公平锁直接尝试 CAS 抢锁。
加锁入口:lock() 方法调用路径一致
无论公平还是非公平锁,lock() 都最终调用 AQS 的 acquire(1)。真正分叉发生在 tryAcquire(int) 的具体实现里:
- 公平锁使用
FairSync.tryAcquire - 非公平锁使用
NonfairSync.nonfairTryAcquire(或重写的tryAcquire)
关键差异:是否让新线程“插队”
当锁空闲(state == 0)时:
- 非公平锁:跳过排队检查,立即执行
compareAndSetState(0, acquires)尝试抢锁 - 公平锁:先调用
hasQueuedPredecessors()—— 若返回true(说明队列中有更早等待的线程),直接放弃抢锁,进入队列排队;仅当返回false才执行 CAS
注:hasQueuedPredecessors() 实质判断 head.next != null && head.next.thread != current,即头结点后是否有别的有效等待节点。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
锁重入逻辑完全相同
一旦锁已被当前线程持有(getExclusiveOwnerThread() == current),两者都允许重入,并通过增加 state 值记录重入次数,这部分代码无任何差异。
构造方式决定锁类型
ReentrantLock 默认是非公平锁:
-
new ReentrantLock()→NonfairSync -
new ReentrantLock(true)→FairSync
底层通过构造器传参选择不同 Sync 子类,从而绑定各自的 tryAcquire 行为。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










