AQS需继承并重写关键方法来定制锁,核心是定义匹配业务需求的state值,如限流用剩余令牌数、资源池用空闲连接数、多级审批用掩码、可重入锁用持有次数;只需实现独占或共享一种模式及必要方法,并确保CAS/volatile语义与acquire/unlock严格对应。

AQS 机制不是拿来直接用的,而是通过继承并重写关键方法,把业务中“什么算抢到资源”“什么算释放资源”这些逻辑填进去,从而定制出贴合场景的锁工具类。
明确你要控制的业务状态
所有自定义锁的核心,是定义一个能代表业务许可状态的 state 值。它不一定是“0/1 表示有无锁”,而要匹配真实需求:
- 限流场景:state 可表示剩余令牌数,每次 acquire 减 1,release 加 1
- 资源池管理:state 表示空闲连接数,获取连接时 tryAcquire 尝试扣减,归还时 tryRelease 增加
- 多级审批锁:state 为整型掩码,每位代表一个审批环节是否通过
- 可重入计数器锁:state 记录当前线程持有次数,而非单纯布尔值
只实现真正需要的模式和方法
AQS 支持独占(Exclusive)和共享(Shared)两种模式,多数业务只需一种:
- 做互斥访问(如防重复提交、单实例操作),继承 AQS 后重写 tryAcquire 和 tryRelease
- 做信号协同(如等待多个子任务完成才继续),用 tryAcquireShared 和 tryReleaseShared
- 不需要中断支持?可以不调用 acquireInterruptibly;不需要超时?跳过 tryAcquireNanos
- 不用条件变量(Condition)?就不用暴露 newCondition() 方法,也不需实现 ConditionObject 相关逻辑
封装成易用的 Lock 接口实现
对外提供标准 Lock 行为,内部委托给 AQS 子类。例如一个简单“最多 N 个线程并发执行”的公平限流锁:
立即学习“Java免费学习笔记(深入)”;
public class MaxConcurrentLock implements Lock {
private static class Sync extends AbstractQueuedSynchronizer {
Sync(int permits) { setState(permits); }
protected int tryAcquireShared(int acquires) {
for (;;) {
int current = getState();
if (current == 0) return -1; // 满了
if (compareAndSetState(current, current - 1)) return 1;
}
}
protected boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();
if (compareAndSetState(current, current + 1)) return true;
}
}
}
private final Sync sync = new Sync(5); // 允许最多 5 个并发
public void lock() { sync.acquireShared(1); }
public void unlock() { sync.releaseShared(1); }
// 其他方法略...
}
注意线程安全与语义一致性
state 的读写必须基于 CAS 和 volatile 语义,不能在 tryAcquire 中做非原子判断再 set;同时确保:
- acquire 成功后,业务线程一定拿到许可;失败则一定进入队列或返回
- unlock 必须严格对应一次 acquire,避免 state 错乱(比如未加锁就解锁)
- 若支持可重入,需在 tryAcquire 中检查当前线程是否已持有,再更新 state
- 调试时可用 hasQueuedThreads()、getQueueLength() 辅助观察排队情况


















