aqs 是 java 并发包中实现锁和同步器的底层骨架,通过封装状态管理、线程排队和唤醒/阻塞等共性逻辑,由子类实现 tryacquire、tryrelease 和 isheldexclusively 等核心方法,并结合 volatile int state 控制锁状态,配合 clh 队列自动管理等待线程,最终通过实现 lock 接口提供标准 api。

AQS 是 Java 并发包中实现锁和同步器的底层骨架,它不直接提供锁,而是把“状态管理”“线程排队”“唤醒/阻塞”这些共性逻辑封装好,把关键决策点留给子类去定义。自定义锁的本质,就是继承 AQS 并按需实现几个核心方法,再用它包装出符合 Lock 接口语义的对外 API。
锁的状态由 state 变量统一控制
AQS 内部用一个 volatile int state 表示同步状态,它的含义完全由你定义。比如:
- state == 0:表示锁空闲,无人持有
- state == 1:表示已被某个线程独占(不可重入锁)
- state > 1:可表示重入次数(如 ReentrantLock)
修改 state 必须保证原子性,所以推荐使用 compareAndSetState(expect, update),它基于 Unsafe 的 CAS 操作,避免竞态。
独占式获取与释放逻辑要自己写
要实现一把互斥锁,必须重写 AQS 的三个关键模板方法:
-
tryAcquire(int arg):尝试获取锁。典型做法是判断 state 是否为 0,若是,用 CAS 将其设为 1,并调用
setExclusiveOwnerThread(Thread.currentThread())记录持有者;成功返回 true,失败返回 false -
tryRelease(int arg):尝试释放锁。先校验当前线程是否为持有者(
isHeldExclusively()),再将 state 设为 0、清空 owner 线程;成功返回 true -
isHeldExclusively():判断当前线程是否正持有该锁,通常只需比较
getExclusiveOwnerThread() == Thread.currentThread()
这些方法不负责线程挂起或排队——那是 AQS 自己在 acquire() 和 release() 中协调完成的。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
等待队列自动管理阻塞线程
当线程调用 lock() 却发现锁已被占,AQS 会把它封装成一个 Node 节点,加入内部的 FIFO 双向链表(CLH 队列变种)。这个过程全自动,无需手动干预。
节点入队后,AQS 会让它在队列中自旋检查前驱是否为头节点;一旦前驱释放锁并唤醒它,它就再次尝试 tryAcquire。整个过程屏蔽了 wait/notify 或 LockSupport.park/unpark 的复杂细节。
对外暴露标准 Lock 接口更实用
虽然 AQS 提供了 acquire(1) 和 release(1),但用户习惯的是 Lock.lock() 和 Lock.unlock()。因此建议让自定义锁类实现 java.util.concurrent.locks.Lock 接口,并在其内部持有一个 AQS 子类实例:
-
lock()方法内部调用sync.acquire(1) -
unlock()方法内部调用sync.release(1) - 还可选择性实现
newCondition(),返回sync.newCondition(),支持 await/signal
这样既复用了 AQS 的可靠性,又保持了与 JDK 标准锁一致的编程体验。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










