当前位置: 首页 > news >正文

【深入解析——AQS源码】

深入解析 AQS 源码

一、前言

在 Java 并发编程的世界里,AbstractQueuedSynchronizer(简称 AQS)是 JUC 包的核心基础组件。常见的同步工具类,例如 ReentrantLockSemaphoreCountDownLatchFutureTask 等,底层都依赖 AQS 来实现。理解 AQS 的设计和源码,可以帮助我们透彻掌握 Java 并发工具的原理。


二、AQS 的核心思想

AQS 的核心是 同步状态 + 队列管理

  1. state 变量:通过一个 volatile int state 表示同步状态(例如锁是否被占用,剩余许可证数量等)。
  2. FIFO 队列:使用一个变种的 CLH 双向队列来管理等待的线程。
  3. 模板方法模式:获取/释放锁的通用逻辑由 AQS 实现,具体的 tryAcquire/tryRelease 逻辑交由子类实现。

三、源码核心结构

1. state 的操作

AQS 提供了对同步状态的安全操作:

protected final int getState() { return state; }
protected final void setState(int newState) { state = newState; }
protected final boolean compareAndSetState(int expect, int update) {return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

这里通过 CAS 保证并发下的原子操作。


2. 独占模式与共享模式

AQS 同时支持两种抽象方法模式:

  • 独占模式:典型代表 ReentrantLock

    • acquire(int arg) / tryAcquire(int arg):定义模板方法,由子类实现,其他也是
    • release(int arg) / tryRelease(int arg):定义模板方法,由子类实现,其他也是
  • 共享模式:典型代表 SemaphoreCountDownLatch

    • acquireShared(int arg) / tryAcquireShared(int arg)
    • releaseShared(int arg) / tryReleaseShared(int arg)

3. acquire 的核心流程(独占模式)

public final void acquire(int arg) {if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();
}

执行流程:

  1. tryAcquire:尝试获取锁,子类实现。
  2. 如果失败,addWaiter 将线程加入等待队列。
  3. acquireQueued:在队列中自旋阻塞,直到前驱节点释放资源。

4. Node 节点(CLH 队列)

队列中的线程由 Node 表示:

static final class Node {static final Node SHARED = new Node();static final Node EXCLUSIVE = null;volatile int waitStatus;volatile Node prev;volatile Node next;volatile Thread thread;
}
  • waitStatus 标识节点状态(如 SIGNAL、CANCELLED)。
  • 通过 prev/next 链接形成双向队列。

四、典型应用

1. ReentrantLock(独占模式)

static final class NonfairSync extends Sync {final void lock() {if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}protected final boolean tryAcquire(int acquires) {// 可重入逻辑}
}

ReentrantLock 通过重写 tryAcquire 来定义获取锁的逻辑,其他排队/阻塞流程交由 AQS 完成。


2. CountDownLatch(共享模式)

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;}
}
  • await() 依赖 acquireShared,当 state=0 时继续执行。
  • countDown() 调用 releaseShared,逐步减少计数,直到为 0 时唤醒所有等待线程。

五、总结

  • AQS 核心state 表示同步状态,CLH 队列管理线程,模板方法模式解耦逻辑。
  • 独占/共享模式:灵活支持多种并发工具。
  • 典型实现ReentrantLockSemaphoreCountDownLatch 等。
  • 模板方法:AQS只是定义对应的tryrelease、tryAcquire等try-xxx抽象方法,对应的方法都是由对应的实现类来实现,并且不强制子类去实现,但是使用时候必须重写,否则报错。

AQS 的设计极其优雅,它把“排队 + 阻塞 + 唤醒 + 状态管理”抽象了出来,真正实现了并发工具类的可复用性。理解 AQS,等于掌握了 JUC 的灵魂。

http://www.dtcms.com/a/358768.html

相关文章:

  • OpenCV安装及其开发环境配置(Windows系统Visual Studio 2022)
  • 【物联网】MQTT / Broker / Topic 是什么?
  • 【分享】如何显示Chatgpt聊天的时间
  • 【Android】JSONObject和Gson的使用
  • 数据结构青铜到王者第十三话---优先级队列(堆)(2)
  • 中级函数三
  • 如何使用 DeepSeek 帮助自己的工作?—— 从效率工具到能力延伸的实战指南
  • BGP路由协议(四):工作原理
  • Redis 持久化配置
  • 使用python格式化nginx配置文件
  • 【系统分析师】高分论文:论系统测试技术及应用
  • xAI发布全新编码模型 grok‑code‑fast‑1!
  • SpringBoot防止重复提交(2)
  • day44-Ansible变量
  • 联合体和枚举——嵌入式学习笔记
  • 每日算法题【二叉树】:二叉树的最大深度、翻转二叉树、平衡二叉树
  • 【系统分析师】高分论文:论软件的系统测试及应用
  • 栈溢出问题
  • Redis-数据类型的常用操作命令
  • uart学习
  • Jdk动态代理 Cglib动态代理
  • MYSQL表结构优化场景
  • 解构机器学习:如何从零开始设计一个学习系统?
  • folium地图不显示加载不出来空白问题解决
  • SAP PP模块的MPS
  • 福彩双色球第2025100期篮球号码分析
  • git在push和clone等操作时显示‘: Invalid argument
  • 优选算法:二分查找
  • #5:Nginx核心使用技术
  • Java 学习笔记(基础篇12)