---
title: AQS 四大核心机制
type: concept
domain: java-concurrency
tags: [aqs, abstract-queued-synchronizer, clh-queue, exclusive, shared, reentrant-lock, semaphore, countdownlatch]
status: learning
created: 2026-09-26
last_reviewed: 2026-09-26
method: code-reading
related_questions:
  - "如何理解AQS？"
related_knowledge:
  - ./concurrency-foundations.md
  - ./synchronized-mechanism.md
  - ./jmm-volatile-cas.md
anki_cards: 5
interview_rounds:
  - "2026-09-26-round-1-Q5"
  - "2026-09-29-round-1-Q6"
---

# AQS 四大核心机制

> AQS 全称 + volatile int state + CLH 双向队列 + 独占/共享两种模式 + 模板方法设计。是 JUC 并发包的基座。

## TL;DR（30 秒扫完）

- **AQS = AbstractQueuedSynchronizer**（抽象队列同步器），位于 `java.util.concurrent.locks` 包
- **两大核心数据结构**：`volatile int state`（同步状态）+ CLH 双向队列（head/tail）
- **两种工作模式**：独占（tryAcquire/tryRelease）+ 共享（tryAcquireShared/tryReleaseShared）
- **模板方法模式**：父类负责排队调度，子类负责判断"能不能拿到锁"
- **主要子类**：ReentrantLock（state=重入次数）、Semaphore（state=剩余许可）、CountDownLatch（state=倒计时）

## 关键结论

- **结论 A**：AQS 是 JUC 并发包的基座，ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier、ReadWriteLock 都直接或间接继承它
- **结论 B**：两大核心数据结构——`volatile int state` 记录同步状态（含义由子类决定）+ CLH 双向队列用于排队等待
- **结论 C**：两种工作模式——独占模式（一次一个线程，如 ReentrantLock）+ 共享模式（多个线程可同时，如 ReadLock、Semaphore）
- **结论 D**：模板方法模式是 AQS 设计优雅的关键——父类负责排队、唤醒、调度，子类只实现"拿到锁/释放锁"的判断逻辑

## 完整讲解（费曼四步）

### STEP 1 · 概念

AQS 全称 AbstractQueuedSynchronizer（抽象队列同步器），是 JUC 并发包的基座。它通过一个 `volatile int state` 变量和 CLH 双向队列，把"如何判断能不能拿到锁"和"如何调度等待线程"解耦，让子类只需实现判断逻辑。

### STEP 2 · 大白话

> **类比**：AQS 就像一个"排队取号系统"。
>
> - `state` 是"当前柜台的服务状态"（比如"剩余许可数"或"重入次数"）
> - CLH 队列是"等候区"，取不到号的线程挂在这里
> - 独占模式 = "一次只服务一个人"（如 ReentrantLock）
> - 共享模式 = "多人同时服务"（如 Semaphore 限流 5 个）
> - 模板方法 = "系统负责叫号排队，店员只负责判断能不能服务"

### STEP 3 · 底层

#### 两大核心数据结构

| 结构 | 类型 | 含义 |
|------|------|------|
| **state** | `volatile int` | 同步状态，含义由子类决定。ReentrantLock=重入次数、Semaphore=剩余许可、CountDownLatch=倒计时 |
| **CLH 双向队列** | Treiber 队列变种 | 获取锁失败的线程被封装成 Node 节点挂到队尾。head=头节点（持锁线程），tail=尾指针 |

**Node 结构**：
- `prev` / `next`：双向链表指针
- `waitStatus`：节点状态（SIGNAL/WCANCELED/PROPAGATE/CONDITION）
- `thread`：等待的线程
- `nextWaiter`：条件队列节点（共享/独占标记）

#### 两种工作模式

| 模式 | 含义 | 子类实现 | 典型例子 |
|------|------|---------|---------|
| **独占模式** | 一次只有一个线程能持有 | `tryAcquire` / `tryRelease` | ReentrantLock、ReadWriteLock 写锁 |
| **共享模式** | 多个线程可同时持有 | `tryAcquireShared` / `tryReleaseShared` | ReadLock、Semaphore、CountDownLatch |

#### 独占 vs 共享的核心区别

| 维度 | 独占模式 | 共享模式 |
|------|---------|---------|
| 允许进入的线程数 | 1 个 | 多个 |
| 模板方法 | `tryAcquire(int)` | `tryAcquireShared(int)` |
| `state` 语义 | 0=空闲，非0=持有次数 | 允许多线程共享 state（如剩余许可）|
| 释放方法 | `tryRelease(int)` | `tryReleaseShared(int)` |
| 返回语义 | 独占获得/释放（boolean）| 共享获得/释放（返回剩余量）|

**核心区别只有一个**：能不能同时允许多个线程进入临界区。

#### ReadWriteLock = 双 AQS 实例组合

```java
public class ReentrantReadWriteLock {
    private final Sync sync = new Sync();  // ← 单一 Sync 内部维护 readCount + writeHold
    // 但从 AQS 使用角度，读锁和写锁表现为两个"独立的同步语义"
}
```

- **WriteLock**：独占模式，`state` 高 16 位存写锁重入次数
- **ReadLock**：共享模式，`state` 低 16 位存读锁持有数
- 一个 `Sync` 内同时维护两种语义——但对外表现为两个 AQS 实例
- **面试口径**：ReadWriteLock 是"独占+共享"的组合，写独占 + 读共享

#### 主要子类及 state 含义

| 子类 | state 含义 | 模式 |
|------|-----------|------|
| ReentrantLock | 重入次数（0=未持有，N=重入 N 次） | 独占 |
| ReentrantReadWriteLock | 高 16 位=写锁重入次数，低 16 位=读锁持有数 | 混合（双 AQS）|
| Semaphore | 剩余许可数 | 共享 |
| CountDownLatch | 倒计时（0=到达终点） | 共享 |
| CyclicBarrier | 参与线程数 | 共享 |
| Phaser | 注册/到达计数 | 共享 |

#### 独占/共享组件完整清单

| 组件 | 模式 |
|------|------|
| ReentrantLock | 独占 |
| ReentrantReadWriteLock.WriteLock | 独占 |
| ReentrantReadWriteLock.ReadLock | 共享 |
| Semaphore | 共享 |
| CountDownLatch | 共享 |
| CyclicBarrier | 共享 |
| Phaser | 共享 |
| StampedLock（读优化） | 混合（读无锁化） |

#### 常见误区（独占/共享专项）

- **误区**：MySQL 读写锁就是 AQS 独占/共享 → 错误。MySQL 读写锁是**混合模式**，等价于 Java 的 ReadWriteLock（双 AQS 组合）
- **误区**：共享模式的 state 表示"持有锁的线程数" → 错误。共享模式的 state 语义由子类决定，Semaphore=剩余许可、CountDownLatch=倒计时

#### 模板方法模式

```
父类 AQS：
  - acquire() → tryAcquire() → 成功则设置 owner，失败则入队
  - release() → tryRelease() → 唤醒后继线程
  - 负责：排队、唤醒、调度

子类 ReentrantLock：
  - tryAcquire() → 判断 state 是否为 0 或是否已持有
  - tryRelease() → state-- 判断是否为 0
  - 只负责：判断逻辑
```

#### 主要子类及 state 含义

| 子类 | state 含义 | 模式 |
|------|-----------|------|
| ReentrantLock | 重入次数（0=未持有，N=重入 N 次） | 独占 |
| ReentrantReadWriteLock | 高 16 位=写锁重入次数，低 16 位=读锁持有数 | 混合 |
| Semaphore | 剩余许可数 | 共享 |
| CountDownLatch | 倒计时（0=到达终点） | 共享 |
| CyclicBarrier | 参与线程数 | 共享 |

#### 与 synchronized 对比

| 维度 | synchronized | AQS (ReentrantLock) |
|------|-------------|---------------------|
| 实现 | JVM 内置 | 用户态 |
| 可中断 | ✗ | ✓（lockInterruptibly） |
| 可超时 | ✗ | ✓（tryLock(timeout)） |
| 公平性 | 非公平锁 | 可选（isFair 构造参数） |
| 多条件变量 | ✗（单 waitSet） | ✓（多个 Condition） |
| 性能 | 低竞争更快 | 高竞争更快（可优化调度） |

### STEP 4 · 简化

> **一句话总结**：AQS = `volatile int state` + CLH 双向队列 + 独占/共享两种模式 + 模板方法。父类负责排队调度，子类只负责判断。ReentrantLock/Semaphore/CountDownLatch 都是它的子类。

## 常见误区

- **误区 1**：AQS 就是 ReentrantLock → 正确：AQS 是基座，ReentrantLock 是子类之一
- **误区 2**：AQS 全称不清楚 → 正确：AbstractQueuedSynchronizer（抽象队列同步器）
- **误区 3**：阻塞队列是 AQS 的核心功能 → 正确：阻塞队列是用 AQS 实现的组件，不是 AQS 本身
- **误区 4**：AQS 只有独占模式 → 正确：有独占和共享两种模式

## 延伸追问

1. **AQS 为什么用双向链表而不是单向？**
   - 释放锁时要唤醒前驱的后继节点（独占）或所有后继（共享），单向链表无法高效遍历
2. **ReentrantLock 怎么实现可重入？**
   - state 记录重入次数，同一线程再次获取时 state++，释放时 state--，直到 0 才真正释放
3. **公平锁 vs 非公平锁的区别？**
   - 公平锁 tryAcquire 时先看 hasQueuedPredecessors（队列里有没有更老的线程）；非公平锁直接 CAS 抢。非公平锁吞吐更高，公平锁避免饥饿

## 速查表（面试前 30 秒扫完）

```
AQS = AbstractQueuedSynchronizer
  两大核心：volatile int state + CLH 双向队列
  两种模式：独占（tryAcquire/tryRelease）+ 共享（tryAcquireShared/tryReleaseShared）
  模板方法：父类调度，子类判断

子类 state 含义：
  ReentrantLock = 重入次数
  Semaphore = 剩余许可数
  CountDownLatch = 倒计时
  ReadLock = 读锁持有数（共享模式）

vs synchronized：
  synchronized = JVM 内置、不可中断、不可超时、非公平
  AQS = 用户态、可中断、可超时、可选公平
```

## 关联题目（题库）

- [ ] 《如何理解AQS？》— 2026-09-26 Round 1 Q5, ⭐⭐

## 关联知识

- [并发与并行基础 + 线程安全](./concurrency-foundations.md)
- [synchronized 实现与三特性](./synchronized-mechanism.md)
- [JMM 与 volatile/CAS](./jmm-volatile-cas.md)

## Anki 候选卡片

1. **正**：AQS 全称？**反**：AbstractQueuedSynchronizer（抽象队列同步器）
2. **正**：AQS 的两大核心数据结构？**反**：volatile int state（同步状态）+ CLH 双向队列（head/tail）
3. **正**：AQS 的两种工作模式？**反**：独占模式（tryAcquire/tryRelease，如 ReentrantLock）+ 共享模式（tryAcquireShared/tryReleaseShared，如 ReadLock）
4. **正**：ReentrantLock 怎么实现可重入？**反**：state 记录重入次数，同线程再次获取时 state++，释放时 state--，直到 0 才真正释放
5. **正**：AQS 和 synchronized 的区别？**反**：synchronized=JVM 内置、不可中断、不可超时；AQS=用户态、可中断、可超时、可选公平

---

*最后更新：2026-09-26*
