AQS是Java并发包中实现锁的核心框架,通过模板方法管理等待队列和state状态,独占锁由tryAcquire/tryRelease实现,共享锁由tryAcquireShared/tryReleaseShared实现,两者共用CLH队列但唤醒逻辑与节点标记不同。

AQS(AbstractQueuedSynchronizer)是 Java 并发包中实现锁和其他同步器的核心框架,它本身不直接定义“独占锁”或“共享锁”,而是通过模板方法提供统一的等待队列管理与状态控制机制。真正的独占/共享语义,由子类重写特定的 tryAcquire、tryRelease(用于独占模式)和 tryAcquireShared、tryReleaseShared(用于共享模式)等钩子方法来体现。
独占锁在 AQS 中的实现逻辑
独占锁意味着同一时刻只允许一个线程获取成功,典型如 ReentrantLock 的非公平/公平实现。
- AQS 内部用一个 int 类型的 state 字段 表示同步状态(例如可重入次数)
- 子类实现 tryAcquire(int arg):决定当前线程是否能获取锁。返回 true 表示成功,AQS 会将当前线程设为独占线程(
setExclusiveOwnerThread(Thread)),并更新 state;返回 false 则触发入队、挂起等后续流程 - tryRelease(int arg) 负责释放锁:若释放后 state 归零,则清空独占线程引用,并返回 true,表示完全释放,可能唤醒后继节点
- AQS 的
acquire()和release()方法封装了“尝试→失败→入队→阻塞→唤醒→重试”的完整流程,但具体成败判断全由子类的 tryXXX 方法决定
共享锁在 AQS 中的实现逻辑
共享锁允许多个线程同时获取成功,典型如 Semaphore、CountDownLatch、ReadWriteLock.ReadLock。
将后端 Java 接口文档转换为前端 TypeScript 类型定义(interface / type)。输入:飞书文档、Spring Boot 接口文档、Swagger/OpenAPI、手写 API 文档等。输出:包含请求参数与响应结果的 .md 文件,含完整 JSDoc 注释。触发关键词:Java 转 TS、接口转换、生成前端类型、接口文档转 TypeScript、DTO/VO/BO 转 interface、后端文档转前端类型、生成接口类型、类型定义生成。
- 子类实现 tryAcquireShared(int arg):返回值有特殊语义——负数 表示获取失败(如 -1),0 表示获取成功但后续共享者不能再获取(临界点),正数 表示获取成功且还有剩余资源,其他线程可继续获取
- tryReleaseShared(int arg) 返回 boolean:true 表示释放后可能有其他线程可被唤醒(比如释放了一个 permit,Semaphore 需唤醒等待者)
- AQS 的
acquireShared()和releaseShared()会根据返回值自动处理传播唤醒:一旦某个节点获取成功且返回值 > 0,AQS 会主动唤醒后续的共享节点,形成“连锁唤醒”效果 - 注意:共享模式下
exclusiveOwnerThread始终为 null,AQS 不维护独占线程,只靠 state 和队列协调
关键区别与共性
两者复用同一套 CLH 同步队列和 state 状态管理,但行为分离清晰:
立即学习“Java免费学习笔记(深入)”;
- 调用路径不同:
lock()走acquire()→tryAcquire();acquireShared()走tryAcquireShared() - 节点标记不同:AQS Node 中
waitStatus相同,但节点入队时会标记Node.EXCLUSIVE或Node.SHARED,唤醒时只唤醒同模式节点(避免共享节点被独占唤醒逻辑干扰) - 唤醒策略不同:独占模式唤醒仅一个后继节点;共享模式可能连续唤醒多个后续共享节点(doReleaseShared 循环传播)
- state 含义由子类定义:对 ReentrantLock 是重入计数;对 Semaphore 是剩余许可数;对 CountDownLatch 是倒计数值——AQS 不关心具体业务含义
自定义锁的小提示
想基于 AQS 写自己的锁?记住几个要点:
- 继承
AbstractQueuedSynchronizer,不要直接 new 它 - 暴露给用户的 API(如 lock/unlock 或 acquire/release)应包装在另一个类里(如 ReentrantLock 包装 Sync 子类),避免把 AQS 细节泄露出去
- 务必保证 tryAcquire/tryRelease 等方法是线程安全的,通常只需操作 state(CAS 或 setState),不建议加额外锁
- 调试时可借助
getQueueLength()、hasQueuedThreads()等 AQS 提供的监控方法观察队列状态

















