AQS底层原理
2026/6/3 22:39:07 网站建设 项目流程

AQS 全称AbstractQueuedSynchronizer(抽象队列同步器),是 Java 并发包(java.util.concurrent.locks)的核心底层框架ReentrantLockCountDownLatchSemaphore等工具都是基于 AQS 实现的。

简单说:AQS 就是一套通用的锁/同步器实现模板,解决了多线程竞争资源时的排队、阻塞、唤醒问题。


一、AQS 核心三大组件

AQS 底层就靠3 个东西实现所有同步逻辑:

1. 同步状态(state 变量)

  • 用一个volatile int state表示资源的占用状态
  • state=0:资源空闲,无线程占用
  • state>0:资源已被占用(重入锁时 state 会累加)
  • 所有线程竞争锁,本质就是修改这个 state 的值

2. 双向链表(CLH 同步队列)

  • 存储抢锁失败的线程,先进先出(FIFO)
  • 每个节点封装:等待线程 + 等待状态 + 前驱/后继节点
  • 作用:线程抢不到锁,就进入队列排队,不浪费 CPU

3. 独占/共享模式

AQS 支持两种同步模式,开箱即用:

  • 独占模式:只有一个线程能持有锁(ReentrantLock
  • 共享模式:多个线程可同时持有锁(CountDownLatchSemaphore

二、AQS 核心工作原理(抢锁 + 排队 + 唤醒全流程)

我们以**独占锁(ReentrantLock)**为例,走一遍完整流程:

步骤1:线程尝试抢锁

线程调用lock()→ 调用 AQS 的tryAcquire(arg)尝试修改state

  1. state=0:用CAS原子修改为 1,抢锁成功,当前线程成为锁持有者
  2. state≠0:如果是重入(当前线程已持有锁),state+1,依然成功
  3. 抢锁失败 → 进入下一步

步骤2:抢锁失败,加入同步队列排队

  1. 把当前线程封装成一个Node 节点
  2. CAS 安全地加入双向链表尾部
  3. 调用LockSupport.park()阻塞当前线程,让出 CPU

步骤3:锁释放,唤醒排队线程

持有锁的线程调用unlock()→ 执行:

  1. state-1,如果state=0表示完全释放锁
  2. 唤醒队列头部的第一个等待线程
  3. 被唤醒的线程重新尝试抢锁,成功则出队,成为新的锁持有者

三、AQS 关键技术细节

1. 为什么用 volatile 修饰 state?

  • 保证多线程之间的可见性:一个线程修改 state,其他线程立刻看到
  • 配合 CAS 实现无锁原子操作,比synchronized更轻量

2. 什么是 CAS?

  • 全称:Compare And Swap(比较并交换)
  • 作用:原子性修改 state,不加锁也能保证线程安全
  • 原理:先比较内存值是否为预期值,是就更新,不是就失败重试

3. 队列节点等待状态(waitStatus)

节点的状态控制线程的阻塞/唤醒:

  • 0:默认状态
  • SIGNAL(-1):后继节点需要被唤醒(最常用
  • CANCELLED(1):线程取消等待
  • CONDITION(-2):在条件队列等待
  • PROPAGATE(-3):共享模式下传播唤醒

4. 公平锁 / 非公平锁

AQS 天然支持两种锁策略:

  • 非公平锁:线程上来直接抢锁,抢不到再排队(ReentrantLock 默认)
    ✅ 优点:吞吐量高
    ❌ 缺点:可能产生线程“饥饿”
  • 公平锁:线程先看队列是否为空,有排队线程就直接进队
    ✅ 优点:所有线程公平获取锁
    ❌ 缺点:性能稍低

四、AQS 模板方法设计模式(核心设计思想)

AQS 是抽象类,它只做通用逻辑,具体业务交给子类实现:

AQS 固定实现(不用改)

  • 线程入队、出队
  • 线程阻塞、唤醒
  • 队列维护
  • CAS 修改 state

子类必须实现(定制逻辑)

子类只需要重写这几个方法:

  • tryAcquire():尝试获取独占锁
  • tryRelease():尝试释放独占锁
  • tryAcquireShared():尝试获取共享锁
  • tryReleaseShared():尝试释放共享锁

一句话总结:AQS 搭骨架,子类填逻辑,极大简化了同步器开发。


五、经典 AQS 实现类

工具类模式核心原理
ReentrantLock独占state=0空闲,state=1占用,重入时state+1
CountDownLatch共享state=计数器,countDown()减1,减到0唤醒所有线程
Semaphore共享state=许可证数量,acquire()拿证,release()还证
ReentrantReadWriteLock共享+独占高16位读锁(共享),低16位写锁(独占)

六、一句话总结 AQS 底层

AQS 使用 volatile state 表示资源状态,用 CLH 双向队列管理抢锁失败的线程,通过 CAS 无锁操作 + LockSupport 阻塞/唤醒,实现了一套高可用的线程同步框架。


总结

  1. 核心三要素volatile state(资源)、CLH 队列(排队)、LockSupport(阻塞唤醒)
  2. 核心流程:尝试抢锁 → 失败入队阻塞 → 释放锁唤醒队首线程
  3. 设计模式:模板方法,AQS 实现通用逻辑,子类定制同步规则
  4. 价值:JUC 所有锁和同步工具的基石,是 Java 高并发的核心底层

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询