ReentrantLock 源码解析与 AQS 扩展
一、ReentrantLock 概述
ReentrantLock
是 Java 并发包中基于 AQS 实现的可重入锁,提供了比synchronized
更灵活的锁控制功能,如可中断锁、公平锁、条件变量等。其核心设计特点:
可重入性:同一线程可多次获取同一把锁而不会死锁
公平 / 非公平可选:通过构造函数指定锁的公平策略
条件变量支持:通过
newCondition()
创建多个条件变量手动锁管理:需显式调用
lock()
和unlock()
二、ReentrantLock 的核心结构
2.1 继承关系与内部类
public class ReentrantLock implements Lock, java.io.Serializable {private final Sync sync;// 基础同步器,继承自AQSabstract static class Sync extends AbstractQueuedSynchronizer { ... }// 非公平锁实现static final class NonfairSync extends Sync { ... }// 公平锁实现static final class FairSync extends Sync { ... }// 构造函数public ReentrantLock() {sync = new NonfairSync(); // 默认非公平锁}public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}
}
2.2 对 AQS 的核心扩展点
ReentrantLock 通过重写 AQS 的以下关键方法实现锁功能:
AQS方法 | 功能描述 | ReentrantLock实现方式 |
tryAcquire | 尝试获取独占锁 | 检查state状态并进行重入逻辑 |
tryRelease | 尝试释放独占锁 | 递减state值 完全释放的时为 true |
isHeldExclusively | 判断当前线程是否持有锁 | 比较当前线程与锁的持有者 |
三、源码深度解析
3.1 非公平锁实现(NonfairSync)
3.1.1 锁获取流程
static final class NonfairSync extends Sync {final void lock() {// 第一步:直接尝试CAS获取锁if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1); // 失败则走AQS标准流程}protected final boolean tryAcquire(int acquires) {return nonfairTryAcquire(acquires);}
}// 非公平锁的尝试获取逻辑
final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {// 锁未被持有,直接CAS竞争if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {// 重入逻辑:增加state值int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;
}
3.1.2 锁释放流程
protected final boolean tryRelease(int releases) {int c = getState() - releases;if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free = false;if (c == 0) {free = true;setExclusiveOwnerThread(null); // 完全释放锁}setState(c); // 更新statereturn free;
}
3.2 公平锁实现(FairSync)
3.2.1 锁获取流程
static final class FairSync extends Sync {final void lock() {acquire(1); // 直接走AQS流程}protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {// 关键区别:检查队列中是否有前驱节点if (!hasQueuedPredecessors() &&compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {// 重入逻辑与非公平锁相同int nextc = c + acquires;if (nextc < 0)throw new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}
}
3.2.2 公平性保证
hasQueuedPredecessors()
方法是公平锁的核心:
public final boolean hasQueuedPredecessors() {Thread first = null; Node h, s;if ((h = head) != null && ((s = h.next) == null ||(first = s.waiter) == null ||s.prev == null))first = getFirstQueuedThread(); // retry via getFirstQueuedThreadreturn first != null && first != Thread.currentThread();}
3.3 可中断锁与超时锁
3.3.1 可中断锁
中端锁是指线程在等待获取锁的过程中,能够响应外部中断信号(Thread.interrupt()
),并收到中断信号后停止等待,退出阻塞状态的锁获取方式。
public void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);
}// AQS中的实现
public final void acquireInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())throw InterruptedException();if (!tryAcquire(arg))doAcquireInterruptibly(arg); // 支持中断的等待逻辑
}private void doAcquireInterruptibly(int arg)throws InterruptedException {final Node node = addWaiter(Node.EXCLUSIVE); // 创建独占模式节点并加入队列boolean failed = true;try {for (;;) {final Node p = node.predecessor(); // 获取前驱节点if (p == head && tryAcquire(arg)) { // 前驱是头节点且能获取锁setHead(node); // 当前节点设为头节点p.next = null; // 帮助GCfailed = false;return;}// 检查是否需要阻塞if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt()) // 阻塞当前线程并检查中断状态throw new InterruptedException(); // 被中断则抛异常}} finally {if (failed)cancelAcquire(node); // 取消获取锁操作}
}
3.3.2 超时锁
超时锁是指 线程在获取锁时,可设置一个最大等待时间,若在该时间内未成功获取锁,则自动放弃等待,返回 “获取失败”*的锁获取方式。其核心特点在于基于“时间触发”自动放弃等待,不需要外部信号干预。
public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}// AQS中的实现
public final boolean tryAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();return tryAcquire(arg) ||doAcquireNanos(arg, nanosTimeout); // 带超时的等待逻辑
}private boolean doAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {if (nanosTimeout <= 0L) // 超时时间已过return false;final long deadline = System.nanoTime() + nanosTimeout; // 计算截止时间final Node node = addWaiter(Node.EXCLUSIVE); // 创建节点加入队列boolean failed = true;try {for (;;) {final Node p = node.predecessor(); // 获取前驱节点if (p == head && tryAcquire(arg)) { // 前驱是头节点且能获取锁setHead(node); // 当前节点设为头节点p.next = null; // 帮助GCfailed = false;return true;}// 计算剩余超时时间nanosTimeout = deadline - System.nanoTime();if (nanosTimeout <= 0L) { // 超时时间已过cancelAcquire(node); // 取消获取锁return false;}// 检查是否需要阻塞以及剩余时间是否足够if (shouldParkAfterFailedAcquire(p, node) &&nanosTimeout > spinForTimeoutThreshold) // 剩余时间足够则阻塞LockSupport.parkNanos(this, nanosTimeout); // 限时阻塞if (Thread.interrupted()) // 检查中断状态throw new InterruptedException();}} finally {if (failed)cancelAcquire(node); // 取消获取锁操作}
}
3.4 条件变量实现
3.4.1 条件变量创建
public Condition newCondition() {return sync.newCondition();
}// Sync类中的实现
final ConditionObject newCondition() {return new ConditionObject();
}
3.4.2 等待与唤醒
// ConditionObject中的await()方法
public final void await() throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();Node node = addConditionWaiter(); // 添加到条件队列int savedState = fullyRelease(node); // 释放锁int interruptMode = 0;while (!isOnSyncQueue(node)) {LockSupport.park(this); // 阻塞线程if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;}// 唤醒后重新竞争锁if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;if (node.nextWaiter != null) // clean up if cancelledunlinkCancelledWaiters();if (interruptMode != 0)reportInterruptAfterWait(interruptMode);
}// ConditionObject中的signal()方法
public final void signal() {if (!isHeldExclusively())throw new IllegalMonitorStateException();Node first = firstWaiter;if (first != null)doSignal(first); // 转移到AQS队列
}
四、ReentrantLock 对 AQS 的扩展总结
4.1 核心扩展点
扩展点 | 实现方式与意义 |
---|---|
可重入性 | 通过 state 计数实现同一线程多次获取锁,释放时需递减至 0 |
公平策略 | 公平锁通过hasQueuedPredecessors() 检查队列顺序,非公平锁直接 CAS 竞争 |
可中断获取 | 重写acquireInterruptibly() 方法,在等待过程中响应中断 |
超时机制 | 实现tryAcquireNanos() 方法,支持带超时的锁获取 |
条件变量 | 通过ConditionObject 实现独立条件队列,支持更精细的线程协作 |
4.2 与 synchronized 的对比
特性 | ReentrantLock | synchronized |
---|---|---|
锁获取方式 | 手动调用 lock () 和 unlock () | 自动获取和释放 |
公平性 | 可选择公平 / 非公平 | 非公平 |
可中断性 | 支持 | 不支持 |
超时锁 | 支持 | 不支持 |
多条件变量 | 支持 | 单一 wait/notify 机制 |
性能 | 高竞争场景更优 | 低竞争场景更简单 |