Skip to content
极高困难

一句话答案

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)。