AQS原理#
一句话答案#
AQS 是 Java 并发包的骨架,核心:volatile int state(资源状态)+ CLH 队列(等待线程),ReentrantLock/Semaphore/CountDownLatch 都基于它。
核心要点
AQS 是 Java 并发包的骨架,ReentrantLock、Semaphore、CountDownLatch、ReentrantReadWriteLock 都基于它实现;CyclicBarrier 是间接依赖(内部用 ReentrantLock + Condition)。
核心设计:
AQS 的两个核心结构:
1. volatile int state → 共享资源的状态(锁计数/许可数等)
2. CLH 队列(双向链表)→ 等待获取资源的线程队列plaintextCLH 队列(FIFO 虚拟队列):
Head(哑节点)← → Node(thread1, CANCELLED) ← → Node(thread2, SIGNAL) ← → Tail
↑
等待被唤醒的线程plaintext每个 Node 的状态(waitStatus):
SIGNAL(-1):后继节点需要被唤醒CANCELLED(1):线程已取消等待CONDITION(-2):在条件队列中等待PROPAGATE(-3):共享模式下传播唤醒
以上 waitStatus 常量和下文的 acquireQueued 是 JDK 8~13 的源码。JDK 14 起 AQS 内部重写(JDK-8229442):Node 改用
status字段(WAITING=1 / CANCELLED=负数 / COND=2),去掉了 PROPAGATE,acquireQueued 合并进统一的acquire(node, arg, shared, interruptible, timed, time)。state + CLH 变体队列 + park/unpark 的整体思路不变。
独占锁的获取流程(以 ReentrantLock 为例):
1. tryAcquire():CAS 尝试将 state 从 0 改为 1
├─ 成功 → 获锁,直接返回
└─ 失败 → 当前线程封装为 Node 加入 CLH 队列尾部
2. 进入 acquireQueued() 自旋:
├─ 前驱节点是 Head?→ 再次 tryAcquire()(此时有机会获锁)
│ ├─ 成功 → 出队,成为新的 Head,返回
│ └─ 失败 → 将前驱 waitStatus 设为 SIGNAL,然后 park() 挂起
└─ 等待前驱节点 unpark() 唤醒 → 重复自旋
3. 释放锁(unlock):
tryRelease() 将 state 减 1(重入几次就要释放几次),减到 0 才算真正释放
unpark(head.next.thread) 唤醒队列中第一个等待线程(next 为空或已取消时从 tail 往前找)plaintext共享模式(Semaphore / CountDownLatch):
- Semaphore:state 是剩余许可数,多个线程可同时持有;减到 0 后再 acquire 的线程排队等待
- CountDownLatch 方向相反:state > 0 时 await 的线程排队,countDown 减到 0 时一次性唤醒所有等待线程
acquireShared()/releaseShared()
面试回答(2分钟版)
AQS 全称 AbstractQueuedSynchronizer,是 Java 并发包的核心骨架,ReentrantLock、Semaphore、CountDownLatch 等都基于它实现。AQS 内部维护两个关键结构:一个 volatile int state 表示资源状态,一个 CLH 双向链表队列存放等待获取资源的线程节点。以 ReentrantLock 为例,线程调用 lock 时先通过 CAS 尝试将 state 从 0 改为 1,成功则直接获锁;失败则把当前线程封装成 Node 加入 CLH 队列尾部,然后检查前驱节点是否为 Head,是的话再尝试一次获锁,仍然失败就将前驱 waitStatus 设为 SIGNAL 并调用 LockSupport.park() 挂起自己。释放锁时 state 减 1,减到 0 才真正释放,然后 unpark 唤醒队列中下一个等待线程。公平锁和非公平锁的区别在于:非公平锁上来直接 CAS 抢,失败才排队;公平锁先检查队列中是否有等待线程,有则老老实实排队。state 在不同实现中含义不同,ReentrantLock 中是重入计数,Semaphore 中是许可数。
追问与易错
追问方向:
- “公平锁和非公平锁在 AQS 中怎么实现的?”→ 公平锁先看队列是否有等待,非公平直接 CAS 抢
- “AQS 的 state 在不同实现中表示什么?”→ ReentrantLock 是重入次数,Semaphore 是剩余许可数,CountDownLatch 是剩余计数,ReentrantReadWriteLock 高 16 位是读锁计数、低 16 位是写锁重入数
- “独占模式和共享模式的区别?”→ 独占 acquire/release,共享 acquireShared/releaseShared
易错点:
- ❌ “AQS 用的是 CAS 自旋”——入队后是 park 阻塞,不是一直自旋
- ❌ 混淆 CLH 队列和 Condition 队列——CLH 是同步队列,Condition 是等待队列