JavaGuide项目解析:深入理解AQS(AbstractQueuedSynchronizer)原理
什么是AQS?
AQS(AbstractQueuedSynchronizer)是Java并发包中的一个核心框架,位于java.util.concurrent.locks
包下。它为构建锁和同步器提供了通用功能的实现,是Java并发编程中最重要的基础组件之一。
AQS的核心作用
AQS主要解决了开发者在实现同步器时的复杂性问题。它提供了一个通用框架,用于实现各种同步器,例如:
- 可重入锁(ReentrantLock)
- 信号量(Semaphore)
- 倒计时器(CountDownLatch)
- 读写锁(ReentrantReadWriteLock)
通过封装底层的线程同步机制,AQS将复杂的线程管理逻辑隐藏起来,使开发者只需专注于具体的同步逻辑。
AQS的核心原理
状态管理
AQS使用一个volatile修饰的int类型变量state
来表示同步状态:
private volatile int state;
状态信息可以通过以下方法进行操作:
protected final int getState() {
return state;
}
protected final void setState(int newState) {
state = newState;
}
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
不同的同步器对state
的解释不同:
- 在ReentrantLock中,
state
表示锁的持有计数 - 在Semaphore中,
state
表示可用许可数量 - 在CountDownLatch中,
state
表示计数器值
CLH队列变体
AQS内部使用CLH锁队列的变体来管理等待线程。CLH锁是一种基于自旋锁的优化实现,AQS对其进行了以下改进:
- 自旋+阻塞混合机制:先短暂自旋尝试获取锁,失败后进入阻塞状态
- 单向队列改为双向队列:便于直接唤醒后继节点
节点状态
AQS中的等待队列节点(Node)有不同的状态:
| 状态 | 值 | 含义 | |-------------|------|----------------------------------------------------------------------| | CANCELLED | 1 | 线程已取消获取锁 | | SIGNAL | -1 | 后继节点需要当前节点唤醒 | | CONDITION | -2 | 节点在等待Condition | | PROPAGATE | -3 | 用于共享模式下解决线程无法唤醒的问题 | | 0 | 0 | 新节点的初始状态 |
AQS的使用方式
自定义同步器
基于AQS实现自定义同步器通常需要以下步骤:
- 继承
AbstractQueuedSynchronizer
- 重写AQS提供的模板方法
AQS提供了5个关键的模板方法:
protected boolean tryAcquire(int arg) // 独占方式尝试获取资源
protected boolean tryRelease(int arg) // 独占方式尝试释放资源
protected int tryAcquireShared(int arg) // 共享方式尝试获取资源
protected boolean tryReleaseShared(int arg) // 共享方式尝试释放资源
protected boolean isHeldExclusively() // 判断是否独占资源
资源共享模式
AQS支持两种资源共享方式:
- 独占模式(Exclusive):只有一个线程能执行,如ReentrantLock
- 共享模式(Share):多个线程可同时执行,如Semaphore/CountDownLatch
AQS源码深度解析
独占模式获取资源
核心方法是acquire()
:
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
流程分为三步:
tryAcquire()
:尝试获取资源(由子类实现)addWaiter()
:获取失败时将线程封装为Node加入队列acquireQueued()
:在队列中等待获取资源
tryAcquire实现示例
以ReentrantLock的非公平锁为例:
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;
}
节点入队(addWaiter)
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
队列中等待(acquireQueued)
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
独占模式释放资源
核心方法是release()
:
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
tryRelease实现示例
以ReentrantLock为例:
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;
}
唤醒后继节点(unparkSuccessor)
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
总结
AQS是Java并发编程的核心框架,它通过状态管理和CLH队列变体实现了高效的线程同步机制。理解AQS的工作原理对于掌握Java并发编程至关重要,也是深入理解各种同步器实现的基础。通过本文的分析,希望读者能够对AQS有一个全面而深入的认识。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考