AQS 是啥

AQS 在 Java 并发里,通常指 AbstractQueuedSynchronizer(抽象队列同步器)。

它是 JUC(java.util.concurrent)里很多锁和同步工具的底层框架。ReentrantLockSemaphoreCountDownLatchReentrantReadWriteLock 等都基于它实现。

一、一句话理解

AQS = 用「一个状态变量 + 一个等待队列」管理线程抢资源、排队、唤醒的通用模板。

你可以把它想成:银行叫号系统

state → 当前还有几个窗口/名额(比如锁是否被占用)

CLH 队列 → 没抢到的人排队

park/unpark → 叫到号唤醒你


二、核心组成

1. state(状态)

一个 volatile int,表示同步状态,含义由子类定义:

工具 state 含义
ReentrantLock 0=未锁,>0=被锁(可重入次数)
Semaphore 剩余许可数
CountDownLatch 还剩几个线程没完成
ReentrantReadWriteLock 高 16 位=读锁数,低 16 位=写锁数

2. CLH 双向队列

抢不到的线程会封装成 Node 放进 FIFO 队列里等待,避免大量线程空转(忙等)。

3. 模板方法

子类只需实现两个方法:

复制代码
// 尝试获取资源(抢锁/抢许可)
protected boolean tryAcquire(int arg)
// 尝试释放资源(放锁/还许可)
protected boolean tryRelease(int arg)

AQS 负责通用的排队、阻塞、唤醒逻辑。


三、工作流程(以独占锁为例)

获取锁(简化理解)

复制代码
public final void acquire(int arg) {
    // 1. 先试着抢
    if (!tryAcquire(arg)) {
        // 2. 抢不到就入队
        // 3. 自旋检查前驱是否是队头
        // 4. 还不行就 park 挂起
    }
}

释放锁

复制代码
public final boolean release(int arg) {
    if (tryRelease(arg)) {
        // 唤醒队列里下一个等待线程
        unparkSuccessor(head);
        return true;
    }
    return false;
}

四、两种模式

模式 说明 典型实现
独占模式(Exclusive) 同一时刻只有一个线程能拿到 ReentrantLockReentrantReadWriteLock 写锁
共享模式(Shared) 多个线程可同时拿到 SemaphoreCountDownLatch、读写锁读锁

五、和 synchronized 的区别

synchronized 基于 AQS 的锁(如 ReentrantLock
实现 JVM 内置,监视器锁 Java 代码实现
灵活性 自动加锁解锁 tryLock、可中断、可超时、可公平
队列 依赖 JVM 实现 明确的 CLH 队列
条件变量 只有一个 wait/notify 可有多个 Condition

ReentrantLocksynchronized 功能多,就是因为 AQS 提供了可扩展的模板。


六、代码里长什么样

ReentrantLock 内部有个继承 AQS 的同步器:

复制代码
// 简化示意,帮助理解
class Sync extends AbstractQueuedSynchronizer {
    protected boolean tryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
            // 没人占锁,CAS 抢
            if (compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
            }
        } else if (current == getExclusiveOwnerThread()) {
            // 重入:同一线程再加锁
            setState(c + acquires);
            return true;
        }
        return false;
    }
    protected boolean tryRelease(int releases) {
        // 释放锁,state 减到 0 时真正放开
        ...
    }
}

业务代码只管 lock() / unlock(),排队和唤醒由 AQS 统一处理。


七、为什么重要

1. 面试常考

  • AQS 是什么?
  • ReentrantLocksynchronized 区别?
  • 公平锁 / 非公平锁怎么实现?

2. 理解并发工具的原理

知道 AQS 后,SemaphoreCountDownLatch 就不再是「黑盒 API」。

3. 和项目的关系

场景 可能用到
接口限流 Semaphore
等待多个任务完成 CountDownLatch
需要可中断/超时加锁 ReentrantLock
线程池 底层也依赖 AQS 协调

你们前面聊的数据库锁、分布式锁、事务,解决的是数据层并发;AQS 解决的是单机 JVM 内线程同步,层次不同,但都服务于「多线程不打架」。


八、常见考点速记

AQS 三件套:

state → 同步状态

CLH 队列 → 等待线程排队

CAS + park → 抢资源 / 阻塞 / 唤醒

子类实现:

tryAcquire → 怎么抢

tryRelease → 怎么放

基于 AQS 的工具:

ReentrantLock

ReentrantReadWriteLock

Semaphore

CountDownLatch

CyclicBarrier(内部也用 ReentrantLock + Condition)


九、一句话总结

AQS 是 Java 并发包的「发动机」:用 state 表示资源状态,用队列管理等待线程,子类只定义「怎么抢、怎么放」,其余排队、阻塞、唤醒都由它统一搞定。

相关推荐
小短腿的代码世界1 小时前
Qt绘图引擎QPainter渲染管线:从光栅化到GPU加速的完整架构——为什么你的2D绘制慢了10倍?
开发语言·qt·架构
一晌小贪欢1 小时前
第26节:自动化办公——利用 Python 自动生成动态分析报告 (PPT/PDF)
开发语言·python·数据分析·自动化·powerpoint·pandas·数据可视化
宋哥转AI1 小时前
@Tool写了但tools/list为空?Spring AI MCP Server注册的两种路径和四个坑
java·agent·mcp
程序喵大人1 小时前
【C++并发系列】第一章:多线程读写同一个变量为什么会出错
开发语言·c++·多线程·并发
xiaoshuaishuai81 小时前
C# vCenter跨云迁移的核心问题
开发语言·c#
兰令水2 小时前
leecodecode【树形DP】【2026.6.11打卡-java版本】
java·算法·深度优先
骑士雄师2 小时前
19.3 langgraph的工作节点和路由函数
java·前端·数据库
fox_lht2 小时前
14.6.将错误重定向到标准错误
开发语言·后端·学习·rust
SWAGGY..2 小时前
Linux系统编程:(十三)环境变量
java·linux·算法