← 每日面试题 学习看板

如何理解AQS?

面试题/00java/02Java 并发编程/02JUC工具类/如何理解AQS?.md

面试记录 2026-09-26

题目:如何理解AQS?

难度:medium

标签:java/juc, general/knowledge

评分:⭐⭐☆☆☆

我的回答

AQS 是 Java 中对于并发编程处理的一系列的工具的整合。核心是锁、阻塞队列以及相应的对于并发相关处理的一系列工具,形成的一个包中内容;

提供了可以更为便捷跟主动控制的一系列锁的操作,以及对多线程的相应支持,包括读写锁、阻塞队列、信号量等一系列的工具。然后最终实现对于整个并发编程方面的支撑。在 JDK1.8 之前,由于 JVM 自己定义的 synchronized 并不是很好用,所以有个大佬写了这套东西。在 JDK1.8 之前并发编程方面的处理,很多其实都是使用 AQS 相关的 API 去做处理的。

点评

优点:知道 AQS 是并发工具的整合基座;举了 ReentrantLock、读写锁、信号量等实现类;有历史感

不足:未说出全称 AbstractQueuedSynchronizer;缺失四大核心机制(state 变量、CLH 队列、独占/共享模式、模板方法);阻塞队列属于用 AQS 实现的组件不是 AQS 本身;对 synchronized 演进史的描述不准确

补充:AQS = state + CLH 双向队列 + 独占/共享两种模式;主要子类 ReentrantLock/ReentrantReadWriteLock/Semaphore/CountDownLatch/CyclicBarrier

完整讲解

第一部分:知识重点剖析

核心考点定位:能否说清 AQS 的全称、state 变量、CLH 队列、独占/共享两种模式,以及模板方法的设计。

知识点拆解:

  1. 全称与定位:AQS = AbstractQueuedSynchronizer(抽象队列同步器),位于 java.util.concurrent.locks 包,是 JUC 并发工具的基座。几乎所有同步器(ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier、ReadWriteLock)都直接或间接继承它
  2. 两大核心数据结构:
  1. 两种工作模式:
  1. 模板方法模式:父类 AQS 负责排队、唤醒、调度;子类只实现"拿到锁/释放锁"的具体判断逻辑。这是 AQS 设计得优雅的关键——把"如何判断"和"如何调度"解耦
  2. 与 synchronized 的区别:
按「底层原理 → 设计权衡 → 工程实践」递进排列。

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. AQS 为什么用双向链表而不是单向?
  1. ReentrantLock 怎么实现可重入?
  1. 公平锁 vs 非公平锁的区别?

第三部分:面试者参考回答(300-600 字口语化)

面试官您好,AQS 全称是 AbstractQueuedSynchronizer,抽象队列同步器,位于 java.util.concurrent.locks 包下,是 JUC 整个并发包的基座。ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier、ReadWriteLock 都是直接或间接继承它。

AQS 的核心有两个:

第一是 volatile int state 状态变量。它记录了同步器的"当前情况",但具体含义由子类决定:ReentrantLock 用 state 表示重入次数,Semaphore 用 state 表示剩余许可数,CountDownLatch 用 state 表示倒计时。state 用 volatile 修饰,保证可见性。

第二是 CLH 双向队列。当线程获取锁失败时,会被封装成一个 Node 节点挂到队列尾部,进入等待。队列头节点代表当前持有锁的线程,队列尾指针是 tail。释放锁时要遍历队列唤醒后继线程。

AQS 有两种工作模式:

独占模式:一次只能一个线程拿到锁,典型例子是 ReentrantLock 和 ReadWriteLock 的写锁。子类实现 tryAcquire 和 tryRelease 两个方法,告诉父类"我拿到了吗"和"我释放了"。

共享模式:多个线程可以同时持有,典型例子是 ReadLock、Semaphore、CountDownLatch。子类实现 tryAcquireShared 和 tryReleaseShared。

AQS 的设计思想是 模板方法模式:父类负责排队、唤醒、调度这些通用逻辑;子类只需要关心"怎么判断能不能拿到锁"和"怎么释放"。这样把"调度"和"策略"解耦,扩展性极强。

和 synchronized 的对比:synchronized 是 JVM 内置的,不可中断、不可超时、公平性由 JVM 决定;AQS 是用户态实现,支持 lockInterruptibly、tryLock(timeout)、isFair 显式控制,所以业务上需要这些能力时就用 AQS 的 ReentrantLock。

典型用法上,需要可中断、可超时、读写分离、信号量限流、倒计时这类场景,基本都是 AQS 的子类。

这就是我对 AQS 的理解。


面试记录 2026-10-20(第 2 次)

题目:如何理解AQS?

难度:medium

标签:java/juc, java/concurrency

评分:⭐⭐⭐☆☆(3/5)

练习次数:2

我的回答

AQS是java中并发编程jut包的核心,其设计思想是通过父类明确好并发编程中关于调度,开始阻塞等逻辑,子类自行实现自己的规则,实现不同的并非线程控制功能;

核心是 三个内容,分别是 state,在不同的子类实现下标识不同的作用,锁中标识持有锁以及可重入锁下持有锁的次数,只有当state归零后才算释放锁;在栅栏中表示要等待线程的数量;

clh队列,用于存放阻塞中的任务,其实现是双端队列,因为不同的子类有些是获取最新的有些是获取最早的任务;

另外是独占和共享模式,独占模式就是一次只有一个线程去执行,其他线程都等待,共享模式类似于读写锁中的读锁,以及栅栏,信号量等模式下同时走多个线程执行也就是同时有多个线程任务在临界区中执行

点评

优点:state / CLH 队列 / 独占与共享三条主线都点到了,比上次(2/5)质变;模板方法的设计意图说得对

不足:① 漏全称 AbstractQueuedSynchronizer;② 双向链表的理由说错——不是为了"取最新/最早",而是释放时要 O(1) 找到前驱、支持取消节点与条件队列转移;③ 没说 tryAcquire/tryRelease、tryAcquireShared/tryReleaseShared、Node.waitStatus;④ "栅栏"(CyclicBarrier)内部其实用 ReentrantLock + Condition,不是直接继承 AQS

补充:AQS 的三件套 = volatile int state + CLH 变体队列 + 模板方法;state 的语义由子类定义(锁=重入次数,Semaphore=许可数,CountDownLatch=计数)

ℹ️ 完整讲解见上方首次记录(2026-09-26)