aqs的独占锁与共享锁本质是两种资源访问策略,区别在于同一时刻允许持有资源的线程数量:独占模式仅限一个线程(如reentrantlock),state表示锁状态或重入次数;共享模式允许多个线程(如semaphore),state表示剩余资源数,获取成功可返回正数,释放可能连环唤醒。

AQS 的独占锁与共享锁,本质是两种资源访问策略,区别在于“同一时刻允许多少线程持有资源”,而 AQS 本身不直接实现锁,只提供统一的排队、阻塞、唤醒和状态管理骨架。
独占模式:一次只给一个线程
适用于排他性场景,比如 ReentrantLock、ReentrantReadWriteLock 的写锁。核心特点是:state 只能被一个线程修改成功,且通常用 state = 1 表示已锁定,>1 表示可重入次数。AQS 不关心“谁加的锁”,只通过 tryAcquire 和 tryRelease 让子类定义获取/释放逻辑。
-
获取失败就入队等待:线程调用
acquire,若tryAcquire返回 false,AQS 自动将其封装为 Node 加入 CLH 队列尾部,并挂起线程 -
释放后唤醒下一个:成功调用
tryRelease后,AQS 检查队列头结点的后继是否在等待(waitStatus == SIGNAL),是则唤醒它 -
可重入靠线程身份判断:比如
getExclusiveOwnerThread() == current成立时,允许 state 累加,不抢占新队列位置
共享模式:多个线程可同时通行
适用于协同型场景,比如 Semaphore(允许多个许可)、CountDownLatch(等待计数归零)、ReentrantReadWriteLock 的读锁。关键在于:state 表示的是“剩余可用资源数”或“待满足的条件值”,不是简单的 0/1 标志。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
获取成功可能仍留余量:
tryAcquireShared返回正数,表示获取成功且还有资源;返回 0 表示刚好用完;负数表示失败(如当前 state 不足) -
释放可能触发连环唤醒:
tryReleaseShared返回 true 时,AQS 会循环唤醒所有后续共享节点,因为多个线程可能同时满足条件(例如 CountDownLatch 中最后一个 countDown 触发所有 await 线程恢复) -
节点状态支持传播:共享节点被唤醒后,若继续调用
doAcquireShared,会尝试将唤醒信号向后传递(PROPAGATE 状态就是为此设计)
state 字段是统一入口,语义由模式决定
state 是 int 类型,不是 boolean,正是因为要兼顾两种模式的需求。在独占模式下,它记录锁的持有次数;在共享模式下,它可能是许可总数、倒计时初始值、或读锁计数。AQS 不解释 state 含义,只保证它的读写具有 volatile 语义,并通过 CAS 原子更新。
- ReentrantLock:state 初始为 0,lock() → state+1,unlock() → state−1
- Semaphore(3):state 初始化为 3,acquire() → state−1(成功时),release() → state+1
- CountDownLatch(5):state 初始化为 5,countDown() → state−1,await() 在 state==0 时才返回
自定义同步器只需专注业务逻辑
AQS 把脏活累活全包了:线程怎么排队、怎么挂起、怎么唤醒、怎么取消、怎么处理中断和超时。你只要继承 AQS,实现几个模板方法即可:
- 独占模式必重写:
tryAcquire、tryRelease - 共享模式必重写:
tryAcquireShared、tryReleaseShared - 用到 Condition 才需实现:
isHeldExclusively
不需要手动操作队列、不用写 CAS 循环、也不用管线程调度细节——这些都由 AQS 的 acquire、release、acquireShared 等模板方法自动完成。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










