AQS不直接实现可重入锁,而是通过state字段记录同一线程重入次数,并结合exclusiveOwnerThread标识持有线程;释放时state递减至0才真正释放并唤醒后继。

AQS(AbstractQueuedSynchronizer)本身不直接实现可重入锁,而是为可重入锁(如 ReentrantLock)提供底层同步框架。可重入性(即同一个线程可多次获取同一把锁)的计数管理与释放逻辑,由具体锁的同步器(继承 AQS 的内部类)在 tryAcquire 和 tryRelease 等模板方法中实现。
计数管理:靠 state 字段 + 当前线程标识
AQS 使用一个 volatile 的 int state 字段表示同步状态。对可重入锁而言,state 不再是简单的 0/1(是否被占用),而是记录当前锁被**同一线程重入的次数**:
- 初始时
state == 0,表示锁空闲; - 首次获取成功时,将
state设为 1,并记录持有线程(setExclusiveOwnerThread(current)); - 同一线程再次调用
lock()时,在tryAcquire中判断当前线程已是持有者,就直接递增state(例如从 1→2、2→3…); - 这个“是否为当前线程”的判断,依赖 AQS 同步器中显式维护的
exclusiveOwnerThread字段(由AbstractOwnableSynchronizer提供)。
释放逻辑:state 递减,零值才真正释放
每次调用 unlock(),最终会进入 tryRelease(int releases) 方法(通常参数固定为 1):
- 先校验当前线程是否为锁持有者,不是则抛
IllegalMonitorStateException; - 将
state减 1; - 若减完后
state == 0,说明重入次数归零,此时才真正释放锁:清空exclusiveOwnerThread,并返回true,触发 AQS 唤醒等待队列中的下一个线程; - 若
state > 0(比如从 2 减到 1),则仅更新计数,不唤醒,返回false—— 锁仍由当前线程持有。
公平性与非公平性的差异点
可重入性逻辑在公平和非公平模式下一致,区别只在获取锁的时机判断:
立即学习“Java免费学习笔记(深入)”;
- 非公平锁:
tryAcquire先尝试 CAS 设置state(可能插队),失败后再检查是否为重入; - 公平锁:
tryAcquire会先调用hasQueuedPredecessors()判断等待队列是否有前驱节点,只有队列为空或自己是首节点时,才继续走重入判断; - 两者对
state的增减、线程归属校验完全相同。
关键代码片段示意(简化版 ReentrantLock.Sync)
// tryAcquire 实现节选(非公平)
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (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;
}
// tryRelease 实现节选
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);
return free;
}


















