外观
一句话答案
AQS 是 Java 并发包的骨架,核心:volatile int state(资源状态)+ CLH 队列(等待线程),ReentrantLock/Semaphore/CountDownLatch 都基于它。
核心要点
AQS 是 Java 并发包的骨架,ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier 都基于它实现。
核心设计:
AQS 的两个核心结构:
1. volatile int state → 共享资源的状态(锁计数/许可数等)
2. CLH 队列(双向链表)→ 等待获取资源的线程队列CLH 队列(FIFO 虚拟队列):
Head(哑节点)← → Node(thread1, CANCELLED) ← → Node(thread2, SIGNAL) ← → Tail
↑
等待被唤醒的线程每个 Node 的状态(waitStatus):
SIGNAL(-1):后继节点需要被唤醒CANCELLED(1):线程已取消等待CONDITION(-2):在条件队列中等待PROPAGATE(-3):共享模式下传播唤醒
独占锁的获取流程(以 ReentrantLock 为例):
1. tryAcquire():CAS 尝试将 state 从 0 改为 1
├─ 成功 → 获锁,直接返回
└─ 失败 → 当前线程封装为 Node 加入 CLH 队列尾部
2. 进入 acquireQueued() 自旋:
├─ 前驱节点是 Head?→ 再次 tryAcquire()(此时有机会获锁)
│ ├─ 成功 → 出队,成为新的 Head,返回
│ └─ 失败 → 将前驱 waitStatus 设为 SIGNAL,然后 park() 挂起
└─ 等待前驱节点 unpark() 唤醒 → 重复自旋
3. 释放锁(unlock):
tryRelease() 将 state 改回 0
unpark(head.next.thread) 唤醒队列中第一个等待线程共享模式(Semaphore / CountDownLatch):
- 多个线程可以同时持有(state > 0),state 减到 0 时后续线程等待
acquireShared()/releaseShared()
追问与易错
追问方向:
- 公平锁和非公平锁在 AQS 中怎么实现的?(公平锁先看队列是否有等待,非公平直接 CAS 抢)
- AQS 的 state 在不同实现中表示什么?(ReentrantLock→重入数,Semaphore→许可数,CountDownLatch→计数)
- 独占模式和共享模式的区别?(独占 acquire/release,共享 acquireShared/releaseShared)
易错点:
- ❌ "AQS 用的是 CAS 自旋"——入队后是 park 阻塞,不是一直自旋
- ❌ 混淆 CLH 队列和 Condition 队列——CLH 是同步队列,Condition 是等待队列
💡 记忆锚点
AQS 像一个银行大厅:state 是柜台上的"叫号牌"(资源状态),CLH 队列是排队等号的人群。独占模式一次只叫一个人(ReentrantLock),共享模式同时叫多人(Semaphore)。拿不到号的人先试着插队问一次,不行就坐下等广播(park),前一个人办完就喊下一位(unpark)。