JAVA并发——什么是AQS?
AQS 就是起到了一个抽象、封装的作用,将一些排队、入队、加锁、中断等方法提供出来,便于其他相关 JUC 锁的使用,具体加锁时机、入队时机等都需要实现类自己控制。
它主要解决三个问题
- 多线程竞争资源时,如何让线程 有序排队?
- 被阻塞的线程,如何 高效挂起/唤醒?
- 如何实现“共享/独占”式访问控制?
核心组成结构:
AQS
│
├─ state:共享资源状态(volatile int,0/1等)
├─ CLH 队列:双向链表,线程排队用
│ └─ Node(head -> node1 -> node2 -> … -> tail)
├─ CAS + LockSupport:实现线程安全和挂起唤醒
├─ 模板方法: tryAcquire/tryRelease/tryAcquireShared/…
它主要通过维护一个共享状态(state)和一个先进先出(FIFO)的等待队列,来管理线程对共享资源的访问。
state 用 volatile 修饰,表示当前资源的状态。例如,在独占锁中,state 为0表示未被占用,为1表示已被占用。
当线程尝试获取资源失败时,会被加入到 AQS 的等待队列中。这个队列是一个变体的 CLH 队列,采用双向链表结构,节点包含线程的引用、等待状态以及前驱和后继节点的指针。
工作原理(流程图级别)
以“独占锁”为例(如 ReentrantLock)
线程A想抢锁 -> 调用 tryAcquire()
↳ 成功?✔:直接拿到锁
↳ 失败?✘:入队排队(CLH 队列)+ 挂起(LockSupport.park)线程B释放锁 -> 调用 release()
↳ 修改 state 状态
↳ 唤醒队列中的下一个等待线程(LockSupport.unpark)