AQS同步器核心原理深度剖析
前言
AQS(AbstractQueuedSynchronizer)是Java并发包java.util.concurrent的核心基础组件,它是实现锁、信号量、倒计时门栓、循环屏障等同步器的基础。理解AQS的原理,对于深入掌握Java并发编程、阅读JUC源码、甚至自定义同步器都至关重要。本文将从设计思想、核心数据结构、源码实现三个维度全面解析AQS。
一、AQS概述
1.1 什么是AQS
AQS是Java并发编程中用于构建锁和同步器的框架。它使用一个int类型的state变量表示同步状态,并通过一个FIFO双向队列管理获取锁失败的线程。
┌─────────────────────────────────────────────────────────────────┐
│ AQS 架构图 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ AbstractQueuedSynchronizer │ │
│ │ │ │
│ │ ┌────────────────┐ ┌──────────────────────────────┐ │ │
│ │ │ state (int) │ │ CLH队列 (FIFO) │ │ │
│ │ │ 同步状态 │ │ ┌────┐┌────┐┌────┐┌────┐ │ │ │
│ │ │ │ │ │T1 ││T2 ││T3 ││T4 │ │ │ │
│ │ │ getState() │ │ └────┘└────┘└────┘└────┘ │ │ │
│ │ │ setState() │ │ ◄──── 队列方向 ────► │ │ │
│ │ │ compareAndSet()│ │ │ │ │
│ │ └────────────────┘ └──────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────┴─────────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌───────────────────────┐ ┌───────────────────────┐ │
│ │ ReentrantLock │ │ Semaphore │ │
│ │ (可重入锁) │ │ (信号量) │ │
│ └───────────────────────┘ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ ┌───────────────────────┐ │
│ │ CountDownLatch │ │ ReentrantReadWrite │ │
│ │ (倒计时门栓) │ │ Lock (读写锁) │ │
│ └───────────────────────┘ └───────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
1.2 AQS的设计思想
/**
* AQS核心设计模式:模板方法
*
* AQS定义了同步器的基本骨架,子类只需要实现特定方法
* 就可以自定义同步行为
*/
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
// 需要子类实现的方法(尝试获取同步状态)
protected abstract boolean tryAcquire(int arg);
// 需要子类实现的方法(尝试释放同步状态)
protected abstract boolean tryRelease(int arg);
// 需要子类实现的方法(判断是否处于锁定状态)
protected abstract boolean isHeldExclusively();
// AQS提供的模板方法(使用tryAcquire)
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
// AQS提供的模板方法(使用tryRelease)
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
}
二、核心数据结构
2.1 CLH队列节点
// Node是CLH队列中的节点
static final class Node {
// 模式标记
static final Node EXCLUSIVE = null; // 独占模式
static final Node SHARED = new Node(); // 共享模式
// 等待状态
static final int CANCELLED = 1; // 取消状态
static final int SIGNAL = -1; // 需要唤醒后继节点
static final int CONDITION = -2; // 等待条件
static final int PROPAGATE = -3; // 传播状态
// 等待状态(volatile)
volatile int waitStatus;
// 前驱节点
volatile Node prev;
// 后继节点
volatile Node next;
// 当前节点代表的线程
volatile Thread thread;
// 下一个等待节点(用于Condition队列)
Node nextWaiter;
// ...
}
2.2 队列结构图
CLH队列结构:
Head Tail
┌────┐ ┌────┐
│Node│◄────────────────►│Node│
│null│ (prev) (next) │ │
│null│ │ T4 │
└┬───┘ └─┬──┘
│ │
│ ▼
│ ┌────────────┐
│ │ prev │◄────────┐
│ │ │ │
│ │ thread │ (T4) │
│ │ │ │
│ │ next │─────┐ │
│ └────────────┘ │ │
│ │ │
▼ │ │
┌───────────┐ │ │
│ │ │ │
│ (空) │ ◄── Head节点 │ │
│ │ 不持有线程 │ │
└───────────┘ │ │
│ │
┌────────────┐ │ │
│ prev │───────────────────────┘ │
│ │ │
│ thread │ (T1) │
│ │ │
│ next │────►┌────────────┐ │
└────────────┘ │ prev │◄────────┘
│ │
│ thread │ (T2)
│ │
│ next │────► ...
└────────────┘
2.3 state状态管理
/**
* 同步状态state的语义由子类定义
*
* ReentrantLock: state表示重入次数(0表示未被持有)
* Semaphore: state表示剩余许可数
* CountDownLatch: state表示计数器值
* ReentrantReadWriteLock: 高16位读锁计数,低16位写锁计数
*/
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer {
// 同步状态 - 使用volatile保证可见性
private volatile int state;
// 获取状态
protected final int getState() {
return state;
}
// 设置状态
protected final void setState(int newState) {
state = newState;
}
// CAS设置状态(JDK推荐的方式)
protected final boolean compareAndSetState(int expect, int update) {
return U.compareAndSwapInt(this, STATE, expect, update);
}
}
三、独占模式源码解析
3.1 acquire流程
/**
* acquire - 独占模式获取同步状态
*
* 流程:
* 1. tryAcquire尝试获取
* 2. 获取成功,直接返回
* 3. 获取失败,加入等待队列
* 4. 在队列中自旋等待
* 5. 被唤醒后尝试获取
*/
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
// 如果被中断唤醒,恢复中断状态
selfInterrupt();
}
/**
* 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;
}
/**
* enq - 完整入队(包含初始化队列)
*/
private Node enq(Node node) {
for (;;) {
Node t = tail;
if (t == null) {
// 队列为空,需要初始化
if (compareAndSetHead(new Node()))
tail = head;
} else {
// 正常入队
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
/**
* 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; // 帮助GC
failed = false;
return interrupted;
}
// 检查是否需要阻塞
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
/**
* shouldParkAfterFailedAcquire - 检查是否应该阻塞
*
* 只有当前驱节点状态为SIGNAL时才阻塞
* 否则向前传播或重置状态
*/
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
// 前驱节点会唤醒后继节点
if (ws == Node.SIGNAL)
return true;
// 前驱节点已取消,跳过
if (ws > 0) {
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// 设置前驱节点为SIGNAL
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
3.2 release流程
/**
* 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;
}
/**
* 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);
}
3.3 等待队列操作图解
场景:4个线程获取锁,线程1持有锁
初始状态(线程1持有锁):
┌────────────────────────────────────────────────────┐
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │ HEAD │◄────►│ T2 │◄►│ T3 │◄►│ TAIL │ │
│ │ null │ │ wait │ │ wait │ │ │ │
│ │ SIGNAL│ │ -1 │ │ -1 │ │ │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ │
│ │ │
│ │ Lock held by T1 │
│ ▼ │
│ ┌──────┐ │
│ │ T1 │ (当前持有锁) │
│ │ │ │
│ └──────┘ │
└────────────────────────────────────────────────────┘
线程1释放锁,唤醒线程2:
┌────────────────────────────────────────────────────┐
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │ HEAD │◄────►│ T3 │◄►│ TAIL │ │
│ │ null │ │ wait │ │ │ │
│ │ 0 │ │ -1 │ │ │ │
│ └──────┘ └──────┘ └──────┘ │
│ │ │
│ │ T1 released, unpark(T2) │
│ │ T2 wakes up, acquires lock │
│ ▼ │
│ ┌──────┐ │
│ │ T2 │ (now head, holds lock) │
│ │ │ │
│ └──────┘ │
└────────────────────────────────────────────────────┘
T2 head状态(锁被T2持有):
┌────────────────────────────────────────────────────┐
│ ┌──────┐ ┌──────┐ │
│ │ T2 │◄────►│ T3 │ (TAIL) │
│ │ │ │ wait │ │
│ │ -1 │ │ -1 │ │
│ └──────┘ └──────┘ │
│ │ │
│ │ Lock held by T2 │
│ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ T2 executing critical section │ │
│ └──────────────────────────────────────────┘ │
└────────────────────────────────────────────────────┘
四、共享模式源码解析
4.1 acquireShared流程
/**
* acquireShared - 共享模式获取同步状态
*
* 共享模式允许多个线程同时持有同步状态
* 例如:Semaphore信号量、ReadWriteLock读锁
*/
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0) // < 0 表示获取失败
doAcquireShared(arg);
}
/**
* doAcquireShared - 在队列中自旋获取(共享模式)
*/
private void doAcquireShared(int arg) {
// 添加SHARED模式的节点
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head) {
// 前驱是头节点,尝试获取
int r = tryAcquireShared(arg);
if (r >= 0) {
// 获取成功,需要传播给后继节点
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
/**
* setHeadAndPropagate - 设置头节点并传播
*/
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head;
setHead(node);
// 传播:唤醒后继共享节点
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
Node s = node.next;
if (s == null || s.isShared())
doReleaseShared();
}
}
4.2 releaseShared流程
/**
* releaseShared - 共享模式释放同步状态
*/
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
/**
* doReleaseShared - 唤醒后继节点(共享模式)
*/
private void doReleaseShared() {
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
// 唤醒后继节点
if (compareAndSetWaitStatus(h, Node.SIGNAL, 0))
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE)))
continue; // 重试
}
if (h == head) // 如果头节点没变,退出
break;
}
}
五、自定义同步器实现
5.1Mutex(互斥锁)实现
/**
* 自定义互斥锁 - 基于AQS实现
*/
public class Mutex implements Lock {
// 内部Sync类
private static class Sync extends AbstractQueuedSynchronizer {
// 判断是否被占用
@Override
protected boolean isHeldExclusively() {
return getState() == 1;
}
// 尝试获取锁(独占模式)
@Override
protected boolean tryAcquire(int acquires) {
// CAS设置状态为1
if (compareAndSetState(0, 1)) {
// 设置持有锁的线程
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
// 尝试释放锁
@Override
protected boolean tryRelease(int releases) {
if (getState() == 0)
throw new IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
// 创建ConditionObject
Condition newCondition() {
return new ConditionObject();
}
}
private final Sync sync = new Sync();
@Override
public void lock() {
sync.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return sync.tryAcquire(1);
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(time));
}
@Override
public void unlock() {
sync.release(1);
}
@Override
public Condition newCondition() {
return sync.newCondition();
}
}
// 使用示例
public class MutexDemo {
private final Mutex mutex = new Mutex();
public void doSomething() {
mutex.lock();
try {
// 临界区操作
} finally {
mutex.unlock();
}
}
}
5.2 Semaphore(信号量)实现
/**
* 自定义信号量 - 基于AQS实现
*/
public class CustomSemaphore {
private static final class Sync extends AbstractQueuedSynchronizer {
private final int permits;
Sync(int permits) {
this.permits = permits;
setState(permits);
}
// 共享模式获取
@Override
protected int tryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
// 共享模式释放
@Override
protected boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();
int next = current + releases;
if (compareAndSetState(current, next))
return true;
}
}
}
private final Sync sync;
public CustomSemaphore(int permits) {
sync = new Sync(permits);
}
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public void release() {
sync.releaseShared(1);
}
public int availablePermits() {
return sync.getState();
}
}
5.3 CountDownLatch(倒计时门栓)实现
/**
* 自定义倒计时门栓 - 基于AQS实现
*/
public class CustomCountDownLatch {
private static final class Sync extends AbstractQueuedSynchronizer {
Sync(int count) {
setState(count);
}
// 共享模式获取(倒计时到0时才成功)
@Override
protected int tryAcquireShared(int acquires) {
return getState() == 0 ? 1 : -1;
}
// 共享模式释放(计数器-1)
@Override
protected boolean tryReleaseShared(int releases) {
for (;;) {
int c = getState();
if (c == 0)
return false; // 已经是0,无法再释放
int nextc = c - 1;
if (compareAndSetState(c, nextc))
return nextc == 0; // 只有减到0才返回true
}
}
}
private final Sync sync;
public CustomCountDownLatch(int count) {
if (count < 0)
throw new IllegalArgumentException("count < 0");
sync = new Sync(count);
}
// 等待计数器归零
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
// 计数器-1
public void countDown() {
sync.releaseShared(1);
}
// 获取当前计数器值
public long getCount() {
return sync.getState();
}
}
// 使用示例
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CustomCountDownLatch latch = new CustomCountDownLatch(3);
// 启动3个线程
for (int i = 0; i < 3; i++) {
new Thread(() -> {
try {
Thread.sleep(1000);
System.out.println("任务完成");
latch.countDown();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
// 等待所有任务完成
latch.await();
System.out.println("所有任务已完成");
}
}
六、AQS在JUC中的应用
6.1 应用总览
┌─────────────────────────────────────────────────────────────────┐
│ AQS 的应用 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────┐ ┌───────────────────────────────────┐ │
│ │ ReentrantLock │ │ ReentrantReadWriteLock │ │
│ │ │ │ │ │
│ │ tryAcquire() │ │ tryAcquireShared() - 读锁 │ │
│ │ tryRelease() │ │ tryReleaseShared() - 读锁释放 │ │
│ │ isHeldExclusively│ │ tryAcquire() - 写锁 │ │
│ │ │ │ tryRelease() - 写锁释放 │ │
│ │ state = 重入次数 │ │ state = 高16位读+低16位写 │ │
│ └───────────────────┘ └───────────────────────────────────┘ │
│ │
│ ┌───────────────────┐ ┌───────────────────────────────────┐ │
│ │ Semaphore │ │ CountDownLatch │ │
│ │ │ │ │ │
│ │ tryAcquire() │ │ tryAcquireShared() - 等待归零 │ │
│ │ tryRelease() │ │ tryReleaseShared() - 计数-1 │ │
│ │ │ │ │ │
│ │ state = 许可数 │ │ state = 计数器值 │ │
│ └───────────────────┘ └───────────────────────────────────┘ │
│ │
│ ┌───────────────────┐ ┌───────────────────────────────────┐ │
│ │ CyclicBarrier │ │ FutureTask │ │
│ │ │ │ │ │
│ │ 使用ReentrantLock │ │ 使用AQS state管理任务状态 │ │
│ │ + Condition实现 │ │ 0=初始化, 1=运行中, 2=已完成 │ │
│ └───────────────────┘ └───────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
6.2 ReentrantLock与AQS
/**
* ReentrantLock使用AQS的方式:
*
* 1. 内部有FairSync和NonfairSync两种实现
* 2. state表示重入次数
* 3. exclusiveOwnerThread记录持有锁的线程
*/
public class ReentrantLock implements Lock, java.io.Serializable {
private final Sync sync;
// 非公平锁
static final class NonfairSync extends Sync {
@Override
protected boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
// 公平锁
static final class FairSync extends Sync {
@Override
protected boolean tryAcquire(int acquires) {
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;
setState(nextc);
return true;
}
return false;
}
}
}
总结
AQS是Java并发编程的基础设施,理解它需要掌握以下几个核心要点:
- 核心思想:模板方法模式,子类只需实现tryAcquire/tryRelease等方法
- 数据结构:state变量表示同步状态,CLH队列管理等待线程
- 独占模式:同一时刻只有一个线程持有同步状态(ReentrantLock)
- 共享模式:多个线程可以同时持有同步状态(Semaphore)
- 队列操作:addWaiter入队、shouldParkAfterFailedAcquire判断是否阻塞、unparkSuccessor唤醒
- 条件变量:ConditionObject与AQS队列配合实现等待/通知机制
AQS的设计体现了Doug Lea大师对并发控制的深刻理解,是学习Java并发编程不可绕过的重要知识点。