AQS 是啥

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

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

一、一句话理解

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) 同一时刻只有一个线程能拿到 ReentrantLock、ReentrantReadWriteLock 写锁
共享模式(Shared) 多个线程可同时拿到 Semaphore、CountDownLatch、读写锁读锁

五、和 synchronized 的区别

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

ReentrantLock 比 synchronized 功能多,就是因为 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 是什么?
  • ReentrantLock 和 synchronized 区别?
  • 公平锁 / 非公平锁怎么实现?

2. 理解并发工具的原理

知道 AQS 后,Semaphore、CountDownLatch 就不再是「黑盒 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 表示资源状态,用队列管理等待线程,子类只定义「怎么抢、怎么放」,其余排队、阻塞、唤醒都由它统一搞定。

相关推荐
北风toto14 分钟前
KMP 算法详解:从暴力匹配到 O(n+m) 的字符串搜索
java·开发语言·算法
william_yangshun15 分钟前
WordCraft 观察:纯 Rust 重写文字处理器,把文档变成可编程对象
开发语言·后端·rust·文档自动化
weixin1997010801615 分钟前
《京东JOS API:落地方案、接口边界与业务踩坑 —— 联盟免费 vs 商家按量的双轨制》(附python源码)
java·网络·python
衡石科技18 分钟前
从语义准备到模型验收:HENGSHI SENSE Data Agent 的 RAG 与部署工程实践
java·大数据·人工智能·数据分析·rag
G018_star sky♬19 分钟前
java学习日记-多态与好玩的写法
java
dtq042419 分钟前
C++ - 变量
开发语言·c++
撸串-研究生21 分钟前
面向景区的综合服务管理平台设计——以稻城亚丁景区为例【附源码】
java·开发语言·vue.js·前后端分离·稻城亚丁景区
wuyk55521 分钟前
样章-第03讲-FreeRTOS在16KB-RAM上的裁剪与陷阱
c语言·开发语言·stm32·单片机·嵌入式硬件·物联网·系统架构
kiros_wang28 分钟前
网络状态监听&WiFi信息获取:弱网提示、断网兜底方案
开发语言·网络·php
geovindu30 分钟前
rust: pool Pattern (续)
开发语言·后端·设计模式·rust·对象池简写模式