Java并发包AQS队列实现原理
一、文章概述
AQS(AbstractQueuedSynchronizer)是Java.util.concurrent包的核心基石,为ReentrantLock、CountDownLatch、Semaphore等几乎所有并发工具提供了统一的同步实现框架。其核心思想是:用一个volatile修饰的int型state变量表示同步状态,配合一个FIFO的**CLH(Craig, Landin, and Hagersten)**双向等待队列,实现线程的排队、阻塞与唤醒机制,解决了同步器实现的重复劳动问题。
二、核心数据结构
| 组件 | 类型 | 核心作用 |
|---|---|---|
| state | volatile int | 0=无锁,>0=持有锁次数,天然支持可重入 |
| 等待队列 | CLH双向链表 | 存储所有获取锁失败的阻塞线程 |
| Node节点 | 内部类 | 封装线程引用、等待状态、前后指针 |
| 节点状态 | int常量 | SIGNAL(等待唤醒)、CANCELLED(已取消)等 |
三、获取锁核心执行流程
四、节点状态流转
五、关键设计要点
- 无锁化修改:所有对state和队列指针的操作均通过Unsafe类的CAS实现,避免了重量级锁的开销
- 精确唤醒:使用LockSupport.park/unpark替代传统wait/notify,支持单个线程精确唤醒,避免虚假唤醒
- 可扩展架构:采用模板方法模式,子类仅需实现以下5个方法,即可自定义独占/共享同步逻辑:
tryAcquire(int):独占式获取同步状态tryRelease(int):独占式释放同步状态tryAcquireShared(int):共享式获取同步状态tryReleaseShared(int):共享式释放同步状态isHeldExclusively():判断当前线程是否独占同步状态
六、释放锁完整流程(时序图,不考虑可重入场景)
总结
AQS通过"状态变量+CLH等待队列"的极简设计,抽象了并发同步的通用逻辑,将复杂的线程调度封装在框架内部,极大降低了自定义同步器的开发难度,是Java并发编程中最经典的设计之一。