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

【深入解析——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.xdnf.cn/news/19248.html

相关文章:

  • 机器视觉学习-day11-图像噪点消除
  • audioLDM模型代码阅读(二)——HiFi-GAN模型代码分析
  • 对于STM32工程模板
  • 坚鹏请教DEEPSEEK:请问中国领先的AI智能体服务商有哪些?知行学
  • 【CF】Day136——Codeforces Round 1046 (Div. 2) CD (动态规划 | 数学)
  • 0830 C++引用const函数重载结构体类
  • MySQL之事务
  • SQL优化_以MySQL为例
  • ROS2的编译机制和工程组织形式
  • C++:list容器--模拟实现(下篇)
  • (链表)Leetcode206链表反转+Leetcode6删除链表的倒数第N个结点+虚拟头节点使用
  • Linux shell命令扩涨
  • 有限字长效应
  • Qt中的锁和条件变量和信号量
  • 数据结构青铜到王者第十三话---优先级队列(堆)(2)
  • Spring Cloud 和 Dubbo 是目前主流的两大微服务框架,分别代表了两种不同的技术路线
  • Systemd 启动初探
  • IPv6过渡技术6VPE
  • 【MYSQL】GET_LOCK使用方法简单解析
  • 直线与椭圆相交弦长计算公式
  • 【物联网】BLE Fundamentals 核心概念总结-广告-读写特征-LED控制-传感器通知-上下游通信过程
  • hashmap计算key的hash的时候为什么要右移16位
  • [光学原理与应用-329]:ZEMAX - 主要用途与主要功能
  • 复现 RoboDK 机械臂几何校准(Staubli TX2‑90L / TX200)
  • Redis(自写)
  • MySQL 简介
  • RocketMQ源码详解(NameServer启动流程)
  • Altium Designer中电路板设计
  • 【ICO】快速制作ICON教材/使用icofx3快速制作ico
  • 生成对抗网络(GAN):深度学习领域的革命性突破