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

【2025面试常问Java八股】AQS介绍(AbstractQueuedSynchronizer 抽象队列同步器)

经典回答

"AbstractQueuedSynchronizer(AQS)是Java并发包的核心框架,为构建锁和同步器提供了底层支持。像ReentrantLock、Semaphore这些常用并发工具都是基于AQS实现的。它的核心思想是通过一个int类型的state变量表示同步状态,配合CLH队列管理线程的排队与唤醒。"

"AQS使用volatile修饰的state变量表示同步状态,通过CAS操作保证原子性修改。比如ReentrantLock用它记录重入次数,Semaphore用它表示剩余许可数。"

"采用CLH变体的FIFO双向队列管理等待线程。每个线程被封装成Node节点,通过waitStatus标识线程状态(如CANCELLED、SIGNAL)。"

"AQS采用模板方法模式,定义了acquire/release等骨架方法,而将tryAcquire/tryRelease等具体操作交给子类实现,这种设计非常优雅。"

"可以把AQS想象成游乐园的排队系统:游客(线程)先尝试直接进入(tryAcquire)如果满员(获取失败),就去排队区(CLH队列)取号等待当前游客离开(release)时,系统通知下一位游客(unpark)共享模式就像团体票,可以一次性放行多人"

高性能:通过自旋+CAS减少阻塞

灵活性:支持独占/共享两种模式

可扩展:基于模板方法方便实现各种同步器

公平可选:支持公平与非公平策略

"在JUC包中有很多经典实现:

ReentrantLock:可重入独占锁

CountDownLatch:倒计时门闩

Semaphore:信号量控制

ThreadPoolExecutor.Worker:线程池工作线程控制

比如ReentrantLock的公平锁实现,就是在tryAcquire中先检查hasQueuedPredecessors()确保先来先服务。"

"理解AQS的设计,不仅能帮助我们更好地使用JUC工具,当需要实现特定需求的同步器时,也能基于AQS快速开发。"

AQS源码

public abstract class AbstractQueuedSynchronizer

extends AbstractOwnableSynchronizer

implements java.io.Serializable {

}

Java AQS (AbstractQueuedSynchronizer) 深度解析

AQS 是 Java 并发包的核心基础框架,为构建锁和同步器提供了底层支持。理解 AQS 是掌握 Java 并发编程的关键。

一、AQS 核心概念

1. 基本定位

  • 全称:AbstractQueuedSynchronizer

  • 位置java.util.concurrent.locks 包

  • 作用:构建锁和同步器的框架(如 ReentrantLock、CountDownLatch 等)

2. 核心思想

  • CLH 队列:基于 FIFO 等待队列的变种

  • 状态管理:通过单个原子 int 值表示同步状态

  • 模板模式:需要子类实现特定方法

二、核心数据结构

1. 同步状态

private volatile int state; // 关键状态变量

2. 等待队列节点

static final class Node {volatile int waitStatus;    // 等待状态volatile Node prev;         // 前驱节点volatile Node next;         // 后继节点volatile Thread thread;     // 关联线程Node nextWaiter;            // 条件队列链接
}

3. 等待状态值

常量名含义
1CANCELLED线程已取消
-1SIGNAL后继线程需要唤醒
-2CONDITION在条件队列中等待
-3PROPAGATE共享模式下传播唤醒

三、工作原理解析

1. 独占模式(如 ReentrantLock)

2. 共享模式(如 Semaphore)

四、关键方法解析

1. 需要子类实现的方法

方法说明
tryAcquire(int)尝试获取独占锁
tryRelease(int)尝试释放独占锁
tryAcquireShared(int)尝试获取共享锁
tryReleaseShared(int)尝试释放共享锁
isHeldExclusively()是否被当前线程独占

2. 重要模板方法

方法说明
acquire(int)独占式获取锁
acquireInterruptibly(int)可中断获取
tryAcquireNanos(int, long)带超时获取
release(int)独占式释放
acquireShared(int)共享式获取
releaseShared(int)共享式释放

五、AQS 在 JUC 中的应用

1. ReentrantLock

final Sync extends AbstractQueuedSynchronizer {// 实现tryAcquire/tryReleaseprotected final boolean tryAcquire(int acquires) {Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {setState(c + acquires); // 可重入return true;}return false;}
}

2. CountDownLatch

private static final class Sync extends AbstractQueuedSynchronizer {Sync(int count) { setState(count); }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;}}
}

六、AQS 设计精髓

1. 性能优化点

  • CAS 操作:状态变更使用 compareAndSetState

  • 自旋检查:入队前多次尝试获取锁

  • 头节点检查:只有前驱是头节点才尝试获取

2. 公平性实现

// 公平锁实现示例
protected final boolean tryAcquire(int acquires) {if (!hasQueuedPredecessors() && // 检查是否有排队线程compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}// ...
}

3. 条件变量支持

public class ConditionObject implements Condition {private transient Node firstWaiter; // 条件队列头private transient Node lastWaiter;  // 条件队列尾public final void await() throws InterruptedException {Node node = addConditionWaiter();int savedState = fullyRelease(node);// ...}
}

七、AQS 使用示例

自定义互斥锁

class Mutex implements Lock {private final Sync sync = new Sync();static class Sync extends AbstractQueuedSynchronizer {protected boolean tryAcquire(int ignore) {return compareAndSetState(0, 1);}protected boolean tryRelease(int ignore) {setState(0);return true;}}public void lock() { sync.acquire(1); }public void unlock() { sync.release(1); }// 其他方法实现...
}

AQS 通过精妙的设计,将同步器的通用逻辑抽象出来,让开发者只需关注特定同步策略的实现。理解 AQS 的工作机制,不仅能帮助更好地使用 JUC 中的工具类,也能为设计自定义同步组件提供坚实基础。

相关文章:

  • PyCharm使用Anaconda 中的虚拟环境
  • PowerBi如何制作KPI的总览页?
  • 关于AI:记忆、身份和锁死
  • Function calling LLMs 的 MCP:AI开发的双剑合璧
  • [OpenGL]使用OpenGL实现基于物理的渲染模型PBR(下)
  • 大数据应用开发——大数据平台集群部署(四)
  • 【KWDB 创作者计划】_上位机知识篇---Arduino
  • 什么是 C++中的const?
  • SpringBoot Actuator指标收集:Micrometer与Prometheus集成
  • Matlab 基于模型参考自适应法和SVPWM的异步电机控制
  • `ImadcnIdentifierGenerator` 深度解析
  • Java学习笔记(数组,方法)
  • JavaWeb 课堂笔记 —— 16 MyBatis 动态SQL
  • Img2img-turbo 在2080Ti上的测试笔记
  • 双目视觉中的动态畸变矫正与跨视角信息融合
  • 4月19日记(补)算了和周日一块写了 4月20日日记
  • 前端工程化之自动化部署
  • 探秘STM32如何成为现代科技的隐形引擎
  • C++栈操作集合
  • SpringBoot编写单元测试
  • 青海玉树州杂多县发生4.6级地震,震源深度10千米
  • 《“四有”好老师系列丛书》发布,由顾明远总主编
  • 加快从数量增长向品质跃升转变,促进生态空间与城市功能有机共生!龚正调研公园城市建设工作
  • 今年1-3月全国吸收外资2692.3亿元人民币
  • 租到“甲醛房”,租客可以解约吗?租金能要回来吗?
  • 李强主持国务院第十三次专题学习