经典回答
"AbstractQueuedSynchronizer(AQS)是Java并发包的核心框架,为构建锁和同步器提供了底层支持。像ReentrantLock、Semaphore这些常用并发工具都是基于AQS实现的。它的核心思想是通过一个int类型的state变量表示同步状态,配合CLH队列管理线程的排队与唤醒。"
"AQS使用volatile修饰的state变量表示同步状态,通过CAS操作保证原子性修改。比如ReentrantLock用它记录重入次数,Semaphore用它表示剩余许可数。"
"采用CLH变体的FIFO双向队列管理等待线程。每个线程被封装成Node节点,通过waitStatus标识线程状态(如CANCELLED、SIGNAL)。"
"AQS采用模板方法模式,定义了acquire/release等骨架方法,而将tryAcquire/tryRelease等具体操作交给子类实现,这种设计非常优雅。"
"可以把AQS想象成游乐园的排队系统:游客(线程)先尝试直接进入(tryAcquire)如果满员(获取失败),就去排队区(CLH队列)取号等待当前游客离开(release)时,系统通知下一位游客(unpark)共享模式就像团体票,可以一次性放行多人"
高性能:通过自旋+CAS减少阻塞
灵活性:支持独占/共享两种模式
可扩展:基于模板方法方便实现各种同步器
公平可选:支持公平与非公平策略
"在JUC包中有很多经典实现:
ReentrantLock:可重入独占锁
CountDownLatch:倒计时门闩
Semaphore:信号量控制
ThreadPoolExecutor.Worker:线程池工作线程控制
比如ReentrantLock的公平锁实现,就是在tryAcquire中先检查hasQueuedPredecessors()确保先来先服务。"
"理解AQS的设计,不仅能帮助我们更好地使用JUC工具,当需要实现特定需求的同步器时,也能基于AQS快速开发。"
AQS源码
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
}
Java AQS (AbstractQueuedSynchronizer) 深度解析
AQS 是 Java 并发包的核心基础框架,为构建锁和同步器提供了底层支持。理解 AQS 是掌握 Java 并发编程的关键。
一、AQS 核心概念
1. 基本定位
-
全称:AbstractQueuedSynchronizer
-
位置:
java.util.concurrent.locks
包 -
作用:构建锁和同步器的框架(如 ReentrantLock、CountDownLatch 等)
2. 核心思想
-
CLH 队列:基于 FIFO 等待队列的变种
-
状态管理:通过单个原子 int 值表示同步状态
-
模板模式:需要子类实现特定方法
二、核心数据结构
1. 同步状态
private volatile int state; // 关键状态变量
2. 等待队列节点
static final class Node {volatile int waitStatus; // 等待状态volatile Node prev; // 前驱节点volatile Node next; // 后继节点volatile Thread thread; // 关联线程Node nextWaiter; // 条件队列链接 }
3. 等待状态值
值 | 常量名 | 含义 |
---|---|---|
1 | CANCELLED | 线程已取消 |
-1 | SIGNAL | 后继线程需要唤醒 |
-2 | CONDITION | 在条件队列中等待 |
-3 | PROPAGATE | 共享模式下传播唤醒 |
三、工作原理解析
1. 独占模式(如 ReentrantLock)
2. 共享模式(如 Semaphore)
四、关键方法解析
1. 需要子类实现的方法
方法 | 说明 |
---|---|
tryAcquire(int) | 尝试获取独占锁 |
tryRelease(int) | 尝试释放独占锁 |
tryAcquireShared(int) | 尝试获取共享锁 |
tryReleaseShared(int) | 尝试释放共享锁 |
isHeldExclusively() | 是否被当前线程独占 |
2. 重要模板方法
方法 | 说明 |
---|---|
acquire(int) | 独占式获取锁 |
acquireInterruptibly(int) | 可中断获取 |
tryAcquireNanos(int, long) | 带超时获取 |
release(int) | 独占式释放 |
acquireShared(int) | 共享式获取 |
releaseShared(int) | 共享式释放 |
五、AQS 在 JUC 中的应用
1. ReentrantLock
final Sync extends AbstractQueuedSynchronizer {// 实现tryAcquire/tryReleaseprotected final boolean tryAcquire(int acquires) {Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {setState(c + acquires); // 可重入return true;}return false;} }
2. CountDownLatch
private static final class Sync extends AbstractQueuedSynchronizer {Sync(int count) { setState(count); }protected int tryAcquireShared(int acquires) {return (getState() == 0) ? 1 : -1;}protected boolean tryReleaseShared(int releases) {// 自旋减少状态值for (;;) {int c = getState();if (c == 0) return false;int nextc = c-1;if (compareAndSetState(c, nextc))return nextc == 0;}} }
六、AQS 设计精髓
1. 性能优化点
-
CAS 操作:状态变更使用 compareAndSetState
-
自旋检查:入队前多次尝试获取锁
-
头节点检查:只有前驱是头节点才尝试获取
2. 公平性实现
// 公平锁实现示例 protected final boolean tryAcquire(int acquires) {if (!hasQueuedPredecessors() && // 检查是否有排队线程compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}// ... }
3. 条件变量支持
public class ConditionObject implements Condition {private transient Node firstWaiter; // 条件队列头private transient Node lastWaiter; // 条件队列尾public final void await() throws InterruptedException {Node node = addConditionWaiter();int savedState = fullyRelease(node);// ...} }
七、AQS 使用示例
自定义互斥锁
class Mutex implements Lock {private final Sync sync = new Sync();static class Sync extends AbstractQueuedSynchronizer {protected boolean tryAcquire(int ignore) {return compareAndSetState(0, 1);}protected boolean tryRelease(int ignore) {setState(0);return true;}}public void lock() { sync.acquire(1); }public void unlock() { sync.release(1); }// 其他方法实现... }
AQS 通过精妙的设计,将同步器的通用逻辑抽象出来,让开发者只需关注特定同步策略的实现。理解 AQS 的工作机制,不仅能帮助更好地使用 JUC 中的工具类,也能为设计自定义同步组件提供坚实基础。