type
Post
status
Published
date
Oct 14, 2026
slug
aqs
summary
tags
技术探索
category
手写
icon
password
AQS(AbstractQueuedSynchronizer,抽象队列同步器)是 Java 实现锁和同步器的基础框架,比如 ReentrantLock、Semaphore、CountDownLatch。
它的核心原理是 一个 state 状态变量 + CAS + FIFO 等待队列。
state:管理同步状态,比如锁是否被占用、剩余许可证数量。
CAS:通过原子操作修改 state,保证并发安全。
FIFO 等待队列:管理等待线程,线程获取资源失败后进入等待队列,通过 LockSupport 挂起,等待被唤醒后重新尝试获取。
为什么能用于多种同步器?
因为 AQS 就是一个专门抽象出来的同步器框架,把通用的排队、阻塞、唤醒机制封装好了,子类只需要实现不同的资源获取和释放逻辑,就能构建不同的同步器。
同步器 | state 的含义 | 核心区别 |
ReentrantLock | 锁的重入次数 | 独占模式,一个线程持有 |
Semaphore | 剩余许可证数量 | 共享模式,允许多个线程获得许可 |
CountDownLatch | 剩余计数 | 计数归零后允许等待线程通过 |
关键在于:AQS 提供统一的机制,不同同步器定义不同的 state 语义和获取、释放规则。
ReentrantLock 如何与 AQS 交互?加锁和释放时,内部如何操作状态与等待队列?
1. 加锁 lock()
- 锁空闲(state = 0):线程通过 CAS 把 state 从 0 改为 1,并记录自己为锁持有者,加锁成功。
- 同一线程再次加锁:state 加 1,实现可重入。
- 其他线程加锁失败:进入 AQS 等待队列,必要时通过 LockSupport.park() 挂起。
2. 解锁 unlock()
- 持有锁的线程将 state 减 1。
- 如果 state 仍大于 0,说明还有重入层数,锁不释放。
- 如果 state 减到 0,清除持有者,真正释放锁,AQS 唤醒等待队列中的后继线程,让它重新竞争锁。
二、具体例子
假设线程 A、B 竞争同一把 ReentrantLock:

公平锁和非公平锁区别在哪?
公平锁:获取锁前检查 AQS 队列中是否有线程排在自己前面,避免插队。
非公平锁:允许新线程直接竞争空闲锁,即使已有线程排队。
分享
