ReentrantLock 源码逐行超详细注释
我已按照是什么→为什么→怎么做→被谁调用的逻辑,对ReentrantLock源码每一行代码添加极致详细注释,同时嵌入Mermaid流程图/关系图说明核心流程、组件关联,全程以注释+markdown图表形式输出,可直接嵌入源码使用。
一、完整源码 + 逐行终极注释
/*
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain
*/
package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.Collection;
/**
* 【是什么】:可重入互斥锁,实现Lock接口,支持同一线程多次获取锁
* 【为什么】:替代synchronized关键字,提供可中断、可超时、公平/非公平、条件队列等高级功能
* 【核心特性】:可重入、独占、支持公平/非公平模式、基于AQS实现
* 【怎么做】:通过AQS的state状态计数实现重入,通过CLH队列实现线程排队
* 【被谁调用】:JUC并发工具类、业务代码、线程池、并发集合等
*/
public class ReentrantLock implements Lock, java.io.Serializable {
// 序列化UID:是什么-唯一标识序列化版本;为什么-保证序列化兼容性;怎么做-JVM自动使用;被谁调用-序列化机制
private static final long serialVersionUID = 7373984872572414699L;
/**
* 同步器:是什么-锁的核心实现组件,继承AQS;为什么-封装锁的所有同步逻辑;怎么做-提供公平/非公平两种实现;被谁调用-ReentrantLock所有方法
*/
private final Sync sync;
/**
* 【是什么】:AQS同步器的抽象基类,独占锁核心实现
* 【为什么】:抽离公平/非公平锁的公共逻辑,减少代码冗余
* 【怎么做】:继承AQS,用state表示锁重入次数,0=无锁,>0=持有锁
* 【被谁调用】:FairSync、NonfairSync继承,ReentrantLock持有
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
// 序列化UID:是什么-同步器序列化版本;为什么-兼容序列化;怎么做-固定值;被谁调用-JVM
private static final long serialVersionUID = -5179523762034025860L;
/**
* 【是什么】:抽象加锁方法;【为什么】:让公平/非公平锁自定义加锁逻辑;【怎么做】:子类实现;【被谁调用】:ReentrantLock.lock()
*/
abstract void lock();
/**
* 【是什么】:非公平尝试获取锁(核心方法)
* 【为什么】:非公平锁直接抢占锁,无需排队,提升吞吐量
* 【怎么做】:CAS修改AQS state状态,判断是否重入
* 【被谁调用】:NonfairSync.tryAcquire()、ReentrantLock.tryLock()
* @param acquires 获取锁的增量(固定1)
* @return true=获取成功,false=失败
*/
final boolean nonfairTryAcquire(int acquires) {
// 1. 获取当前执行线程:是什么-拿到调用方法的线程;为什么-判断是否重入;怎么做-Thread.currentThread();被谁调用-当前锁竞争线程
final Thread current = Thread.currentThread();
// 2. 获取AQS状态:是什么-state=0无锁,>0持有锁;为什么-判断锁状态;怎么做-AQS.getState();被谁调用-AQS
int c = getState();
// 3. 无锁状态:是什么-锁未被任何线程持有;为什么-可以直接抢占锁;怎么做-CAS修改state
if (c == 0) {
// 4. CAS原子修改state:是什么-原子操作,无锁竞争;为什么-保证多线程安全;怎么做-unsafe.compareAndSwapInt;被谁调用-CPU指令
if (compareAndSetState(0, acquires)) {
// 5. 设置锁持有线程:是什么-标记当前线程独占锁;为什么-支持可重入;怎么做-AQS.setExclusiveOwnerThread;被谁调用-AQS
setExclusiveOwnerThread(current);
// 6. 返回成功:是什么-获取锁完成;为什么-通知上层加锁成功;怎么做-return true;被谁调用-调用方
return true;
}
}
// 7. 可重入判断:是什么-当前线程已持有锁;为什么-支持同一线程多次加锁;怎么做-对比持有线程
else if (current == getExclusiveOwnerThread()) {
// 8. 计算新的重入次数:是什么-state+1;为什么-记录重入层级;怎么做-加法运算;被谁调用-当前持有线程
int nextc = c + acquires;
// 9. 溢出判断:是什么-超过int最大值;为什么-防止计数异常;怎么做-判断负数;被谁调用-锁重入超限场景
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
// 10. 更新重入次数:是什么-无需CAS,单线程独占;为什么-只有当前线程能修改;怎么做-AQS.setState;被谁调用-AQS
setState(nextc);
// 11. 重入获取锁成功
return true;
}
// 12. 获取锁失败:是什么-锁被其他线程持有;为什么-进入排队;怎么做-return false;被谁调用-AQS.acquire()
return false;
}
/**
* 【是什么】:释放锁(核心方法)
* 【为什么】:释放锁资源,唤醒排队线程
* 【怎么做】:state减1,为0时完全释放锁
* 【被谁调用】:ReentrantLock.unlock() → AQS.release()
* @param releases 释放增量(固定1)
* @return true=完全释放,false=重入未释放完
*/
protected final boolean tryRelease(int releases) {
// 1. 计算释放后的state:是什么-重入次数-1;为什么-逐层释放锁;怎么做-减法;被谁调用-当前持有线程
int c = getState() - releases;
// 2. 合法性校验:是什么-只有锁持有者能释放;为什么-防止非法释放;怎么做-对比线程;被谁调用-非法调用线程
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
// 3. 标记是否完全释放:是什么-true=锁空闲;为什么-通知AQS唤醒排队线程;怎么做-布尔变量;被谁调用-AQS
boolean free = false;
// 4. 完全释放判断:是什么-state=0;为什么-锁无持有者;怎么做-判断c=0
if (c == 0) {
free = true;
// 5. 清空持有线程:是什么-释放锁所有权;为什么-标记锁空闲;怎么做-AQS.setExclusiveOwnerThread(null)
setExclusiveOwnerThread(null);
}
// 6. 更新state:是什么-保存重入次数;为什么-记录锁状态;怎么做-AQS.setState
setState(c);
// 7. 返回释放结果
return free;
}
/**
* 【是什么】:判断当前线程是否独占锁
* 【为什么】:支持重入校验、状态查询
* 【怎么做】:对比AQS持有线程与当前线程
* 【被谁调用】:ReentrantLock.isHeldByCurrentThread()
*/
protected final boolean isHeldExclusively() {
// 直接返回线程对比结果:是什么-独占判断;为什么-AQS要求实现;怎么做-==判断;被谁调用-AQS
return getExclusiveOwnerThread() == Thread.currentThread();
}
/**
* 【是什么】:创建条件队列
* 【为什么】:实现wait/notify高级功能
* 【怎么做】:返回AQS的ConditionObject
* 【被谁调用】:ReentrantLock.newCondition()
*/
final ConditionObject newCondition() {
return new ConditionObject();
}
// ========== 状态查询方法(被谁调用:ReentrantLock对外暴露的查询方法) ==========
/**
* 【是什么】:获取锁持有线程;【为什么】:监控/调试;【怎么做】:state=0返回null,否则返回持有线程;【被谁调用】ReentrantLock.getOwner()
*/
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
/**
* 【是什么】:获取重入次数;【为什么】:调试/监控;【怎么做】:独占则返回state,否则0;【被谁调用】ReentrantLock.getHoldCount()
*/
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
/**
* 【是什么】:判断是否加锁;【为什么】:状态查询;【怎么做】:state≠0;【被谁调用】ReentrantLock.isLocked()
*/
final boolean isLocked() {
return getState() != 0;
}
/**
* 【是什么】:反序列化重置锁状态
* 【为什么】:反序列化后锁必须为无锁状态
* 【怎么做】:重置state=0
* 【被谁调用】:JVM反序列化机制
*/
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // 强制重置为无锁
}
}
/**
* 【是什么】:非公平锁同步器(默认实现)
* 【为什么】:吞吐量高,线程可直接抢占锁,无需排队
* 【怎么做】:继承Sync,重写lock/tryAcquire
* 【被谁调用】:new ReentrantLock()/new ReentrantLock(false)
*/
static final class NonfairSync extends Sync {
// 序列化UID
private static final long serialVersionUID = 7316153563782823691L;
/**
* 【是什么】:非公平加锁
* 【为什么】:先直接CAS抢占锁,失败再排队,提升效率
* 【怎么做】:先CAS抢锁,失败调用AQS.acquire()排队
* 【被谁调用】:ReentrantLock.lock()
*/
final void lock() {
// 1. 第一次抢占:是什么-无条件CAS抢锁;为什么-非公平核心;怎么做-compareAndSetState;被谁调用-当前竞争线程
if (compareAndSetState(0, 1))
// 2. 抢锁成功:设置当前线程为持有者
setExclusiveOwnerThread(Thread.currentThread());
else
// 3. 抢锁失败:是什么-进入AQS排队流程;为什么-等待锁释放;怎么做-AQS.acquire(1);被谁调用-AQS
acquire(1);
}
/**
* 【是什么】:尝试获取锁;【为什么】:AQS要求实现;【怎么做】:调用父类nonfairTryAcquire;【被谁调用】AQS.acquire()
*/
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
/**
* 【是什么】:公平锁同步器
* 【为什么】:保证线程按排队顺序获取锁,避免线程饥饿
* 【怎么做】:继承Sync,重写lock/tryAcquire,必须检查队列
* 【被谁调用】:new ReentrantLock(true)
*/
static final class FairSync extends Sync {
// 序列化UID
private static final long serialVersionUID = -3000897897090466540L;
/**
* 【是什么】:公平加锁
* 【为什么】:不允许抢占,必须直接排队,保证公平
* 【怎么做】:直接调用AQS.acquire(),不做CAS抢占
* 【被谁调用】:ReentrantLock.lock()
*/
final void lock() {
// 直接进入排队流程:是什么-公平锁核心;为什么-禁止插队;怎么做-AQS.acquire(1);被谁调用-AQS
acquire(1);
}
/**
* 【是什么】:公平尝试获取锁
* 【为什么】:必须检查队列,只有自己是队首才能抢锁
* 【怎么做】:判断hasQueuedPredecessors()+CAS
* 【被谁调用】:AQS.acquire()
*/
protected final boolean tryAcquire(int acquires) {
// 1. 获取当前线程
final Thread current = Thread.currentThread();
// 2. 获取锁状态
int c = getState();
// 3. 无锁状态
if (c == 0) {
// 4. 公平核心:是什么-判断是否有前置排队线程;为什么-保证FIFO;怎么做-AQS.hasQueuedPredecessors();被谁调用-AQS
if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 5. 可重入逻辑(与非公平一致)
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
// ==================== ReentrantLock 构造方法 ====================
/**
* 【是什么】:无参构造(默认非公平锁)
* 【为什么】:非公平锁吞吐量更高,满足绝大多数场景
* 【怎么做】:初始化NonfairSync
* 【被谁调用】:业务代码new ReentrantLock()
*/
public ReentrantLock() {
sync = new NonfairSync();
}
/**
* 【是什么】:带公平参数的构造
* 【为什么】:支持自定义公平/非公平模式
* 【怎么做】:true=FairSync,false=NonfairSync
* 【被谁调用】:需要公平锁的业务场景
* @param fair true=公平锁,false=非公平锁
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
// ==================== Lock 接口实现(对外核心方法) ====================
/**
* 【是什么】:阻塞加锁(不可中断)
* 【为什么】:最常用的加锁方式
* 【怎么做】:调用sync.lock()
* 【被谁调用】:业务代码、并发工具类
*/
public void lock() {
sync.lock();
}
/**
* 【是什么】:可中断阻塞加锁
* 【为什么】:支持线程中断,避免无限阻塞
* 【怎么做】:调用AQS.acquireInterruptibly(1)
* 【被谁调用】:需要中断响应的场景
*/
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
/**
* 【是什么】:非阻塞尝试加锁(立即返回)
* 【为什么】:不排队,立即获取结果
* 【怎么做】:调用nonfairTryAcquire(1)
* 【被谁调用】:尝试加锁场景
*/
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
/**
* 【是什么】:超时尝试加锁
* 【为什么】:避免无限阻塞,支持超时退出
* 【怎么做】:调用AQS.tryAcquireNanos
* 【被谁调用】:限时等待场景
*/
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
/**
* 【是什么】:释放锁
* 【为什么】:释放锁资源,唤醒排队线程
* 【怎么做】:调用AQS.release(1)
* 【被谁调用】:业务代码finally块
*/
public void unlock() {
sync.release(1);
}
/**
* 【是什么】:创建条件变量
* 【为什么】:实现线程等待/通知
* 【怎么做】:调用sync.newCondition()
* 【被谁调用】:生产者-消费者模式
*/
public Condition newCondition() {
return sync.newCondition();
}
// ==================== 状态查询方法 ====================
public int getHoldCount() { return sync.getHoldCount(); }
public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); }
public boolean isLocked() { return sync.isLocked(); }
public final boolean isFair() { return sync instanceof FairSync; }
protected Thread getOwner() { return sync.getOwner(); }
public final boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
public final boolean hasQueuedThread(Thread thread) { return sync.isQueued(thread); }
public final int getQueueLength() { return sync.getQueueLength(); }
protected Collection<Thread> getQueuedThreads() { return sync.getQueuedThreads(); }
// ==================== 条件队列查询方法 ====================
public boolean hasWaiters(Condition condition) {
if (condition == null) throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}
public int getWaitQueueLength(Condition condition) {
if (condition == null) throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
}
protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null) throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}
/**
* 【是什么】:打印锁状态
* 【为什么】:调试/日志输出
* 【怎么做】:拼接锁状态+持有线程
* 【被谁调用】:日志打印
*/
public String toString() {
Thread o = sync.getOwner();
return super.toString() + ((o == null) ? "[Unlocked]" : "[Locked by thread " + o.getName() + "]");
}
}
二、核心组件关联图(Mermaid)
graph TD
ReentrantLock -->|持有| Sync[Sync 抽象同步器<br>继承AQS]
Sync -->|被继承| NonfairSync[NonfairSync 非公平锁<br>默认实现]
Sync -->|被继承| FairSync[FairSync 公平锁<br>带参构造]
Sync -->|依赖| AQS[AbstractQueuedSynchronizer<br>核心:state+CLH队列]
ReentrantLock -->|对外方法| LockAPI[lock/unlock/tryLock]
ReentrantLock -->|条件队列| Condition[ConditionObject<br>等待/通知]
三、非公平锁加锁流程图(核心流程)
flowchart TD
A["调用lock()"] --> B["CAS尝试抢占锁 state=0→1"]
B -->|成功| C["设置当前线程为独占线程<br/>加锁完成"]
B -->|失败| D["调用AQS.acquire(1)"]
D --> E["执行tryAcquire尝试获取锁"]
E -->|成功| F["加锁完成"]
E -->|失败| G["线程进入CLH队列排队<br/>阻塞等待"]
G --> H["锁释放后被唤醒<br/>重新竞争锁"]
四、公平锁加锁流程图(核心流程)
flowchart TD
A["调用lock()"] --> B["直接调用AQS.acquire(1)"]
B --> C["执行公平tryAcquire"]
C --> D["判断hasQueuedPredecessors<br/>是否有前置排队线程"]
D -->|有排队| E["获取失败,进入队列"]
D -->|无排队| F["CAS抢锁→设置独占线程"]
E --> G["阻塞等待→队首时被唤醒"]
G --> C
五、锁释放流程图(通用)
flowchart TD
A["调用unlock()"] --> B["执行tryRelease state-1"]
B --> C["校验:当前线程是否为持有者"]
C -->|否| D["抛出IllegalMonitorStateException"]
C -->|是| E["state=0?"]
E -->|否| F["更新state,未完全释放"]
E -->|是| G["清空持有线程<br/>完全释放锁"]
G --> H["AQS唤醒CLH队列队首线程"]
六、核心知识点总结(markdown)
1. 是什么
ReentrantLock是JDK1.5提供的可重入独占锁,基于AQS实现,实现Lock接口,支持公平/非公平两种模式。
2. 为什么
- 比
synchronized更灵活:支持可中断、可超时、条件队列、公平模式 - 可重入:同一线程可多次加锁,避免死锁
- 非公平锁吞吐量远高于公平锁
3. 怎么做
- 重入实现:用AQS
state计数,加锁+1,释放-1,state=0表示无锁 - 非公平锁:直接CAS抢占锁,失败再排队
- 公平锁:必须检查队列,禁止插队,严格FIFO
- 线程排队:基于AQS的CLH双向队列实现阻塞/唤醒
4. 被谁调用
- 业务代码:并发安全控制
- JUC组件:线程池、并发集合、CountDownLatch等
- 中间件:分布式锁、限流框架底层

浙公网安备 33010602011771号