程序员面试资料大全|各种技术书籍等资料-1000G
AQS(AbstractQueuedSynchronizer) 是 Java 并发包 (java.util.concurrent.locks
) 的核心基础框架,它为实现阻塞锁和同步器提供了底层支持。JUC 中超过 80% 的同步工具都基于 AQS 构建,包括:
ReentrantLock
Semaphore
CountDownLatch
ReentrantReadWriteLock
ThreadPoolExecutor.Worker
classDiagram
AbstractQueuedSynchronizer <|-- ReentrantLock$Sync
AbstractQueuedSynchronizer <|-- Semaphore$Sync
AbstractQueuedSynchronizer <|-- CountDownLatch$Sync
ReentrantLock$Sync <|-- NonfairSync
ReentrantLock$Sync <|-- FairSync
组件 | 作用 | 实现方式 |
---|---|---|
状态变量 (state) | 同步状态(如锁的重入次数、信号量许可数) | volatile int + CAS 操作 |
CLH 队列 | 存储等待线程的 FIFO 队列 | 双向链表(Node 节点) |
模板方法 | 供子类实现的获取/释放逻辑 | tryAcquire()/tryRelease() 等方法 |
static final class Node {
volatile int waitStatus; // 等待状态(CANCELLED/SIGNAL/CONDITION/PROPAGATE)
volatile Node prev; // 前驱节点
volatile Node next; // 后继节点
volatile Thread thread; // 等待线程
Node nextWaiter; // 条件队列专用
}
public final void acquire(int arg) {
if (!tryAcquire(arg) && // 子类实现获取逻辑
acquireQueued( // 加入等待队列
addWaiter(Node.EXCLUSIVE), arg)) // 创建独占节点
selfInterrupt(); // 恢复中断状态
}
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)) { // CAS设置尾节点
pred.next = node;
return node;
}
}
enq(node); // 队列为空时初始化或CAS失败后自旋入队
return node;
}
final boolean acquireQueued(final Node node, int arg) {
boolean interrupted = false;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) { // 只有前驱是头节点才尝试获取
setHead(node); // 获取成功设置为新头节点
p.next = null; // help GC
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) && // 检查是否需阻塞
parkAndCheckInterrupt()) // 调用LockSupport.park()
interrupted = true;
}
} catch (Throwable t) {
cancelAcquire(node); // 取消获取
throw t;
}
}
ReentrantLock
acquire(int arg)
release(int arg)
Semaphore
, CountDownLatch
acquireShared(int arg)
releaseShared(int arg)
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) { // CAS抢锁
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) { // 重入逻辑
setState(c + acquires);
return true;
}
return false;
}
protected int tryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining)) // CAS扣减许可
return remaining;
}
}
protected boolean tryReleaseShared(int releases) {
for (;;) {
int c = getState();
if (c == 0) return false;
int nextc = c-1;
if (compareAndSetState(c, nextc)) // CAS减少计数
return nextc == 0; // 计数为0时唤醒所有线程
}
}
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
LockSupport.park(this); // 阻塞当前线程
LockSupport.unpark(thread); // 唤醒指定线程
for (;;) { // 自旋避免直接阻塞
if (/*条件满足*/) break;
// 短暂自旋后进入阻塞
}
状态值 | 常量名 | 含义 |
---|---|---|
1 | CANCELLED | 线程已取消等待 |
-1 | SIGNAL | 后继线程需要被唤醒 |
-2 | CONDITION | 线程在条件队列等待 |
-3 | PROPAGATE | 共享模式下状态需要传播 |
public class ConditionObject implements Condition {
private transient Node firstWaiter; // 条件队列头
private transient Node lastWaiter; // 条件队列尾
public final void await() {
Node node = addConditionWaiter(); // 加入条件队列
int savedState = fullyRelease(node); // 完全释放锁
while (!isOnSyncQueue(node)) {
LockSupport.park(this); // 阻塞
}
acquireQueued(node, savedState); // 重新竞争锁
}
}
策略 | 实现原理 | 优点 | 缺点 |
---|---|---|---|
非公平锁 | 新线程直接 CAS 抢锁 | 高吞吐量 | 可能线程饥饿 |
公平锁 | 检查队列是否有等待线程才尝试获取 | 保证顺序性 | 上下文切换多 |
class Mutex extends AbstractQueuedSynchronizer {
// 尝试获取锁
protected boolean tryAcquire(int acquires) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
// 尝试释放锁
protected boolean tryRelease(int releases) {
if (getState() == 0) throw new IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
}
状态设计:
// 正确:使用原子操作管理状态
protected final boolean compareAndSetState(int expect, int update)
// 错误:直接修改state
setState(1); // 非线程安全!
避免死锁:
lock.lock();
try {
// 临界区代码
} finally {
lock.unlock(); // 必须确保释放
}
性能调优:
ReentrantReadWriteLock
JDK 版本 | AQS 改进 |
---|---|
5 | 初始引入 |
6 | 优化 CLH 队列 |
8 | 移除无用的字段,减少内存占用 |
9 | 增强栈跟踪 |
15 | 优化条件队列性能 |
VarHandles(Java 9+):
private static final VarHandle STATE;
STATE.compareAndSet(this, expect, update);
StampedLock:
StampedLock lock = new StampedLock();
long stamp = lock.tryOptimisticRead(); // 乐观读
Virtual Threads(Java 19+):
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> {
// 轻量级线程,无需复杂同步
});
}
程序员面试资料大全|各种技术书籍等资料-1000G