Java自定义共享锁需继承AQS并重写tryAcquireShared(返回≥0表示成功,负数入队)和tryReleaseShared(CAS更新state,返回true触发唤醒),state统一管理许可数,配合acquireShared/releaseShared完成同步流程。

Java 中自定义共享锁通过继承 AbstractQueuedSynchronizer(AQS)实现,核心在于重写其模板方法 tryAcquireShared 和 tryReleaseShared,并配合 setState/getState 管理同步状态。AQS 本身不关心“锁”的语义,只负责排队、阻塞、唤醒等底层协作逻辑;你只需定义“什么情况下允许获取共享资源”以及“释放后是否还有剩余许可”这两个关键语义。
理解共享锁的典型语义
共享锁允许多个线程同时持有(如读锁、信号量),与独占锁(如 ReentrantLock)的关键区别在于:
- 获取成功时,
tryAcquireShared返回 ≥ 0 的值(通常为剩余许可数或固定正数),表示可继续获取或唤醒后续等待者; - 返回负数(如 -1)表示获取失败,当前线程将被加入同步队列并可能挂起;
-
tryReleaseShared必须是线程安全的无锁操作(通常用 CAS),返回true表示可能有其他线程在等待,需唤醒队列头结点。
继承 AQS 实现一个简易共享计数锁
假设我们要实现一个最多允许 permits 个线程并发访问的共享锁(类似 Semaphore 的简化版):
class SimpleSharedLock extends AbstractQueuedSynchronizer {
SimpleSharedLock(int permits) {
setState(permits); // 初始许可数即为 state 值
}
<pre class="brush:php;toolbar:false;">// 尝试获取共享锁:若还有许可,就扣减并返回剩余数;否则返回 -1
protected int tryAcquireShared(int acquires) {
for (;;) {
int current = getState();
int remaining = current - acquires;
if (remaining <p>}</p>注意:tryAcquireShared 返回非负值(如 2)表示获取成功且还有余量,AQS 会自动尝试唤醒后续共享节点;返回负值则入队等待。
封装成易用的 Lock 接口实现
AQS 是同步器基类,不是 Lock。要对接标准 API,需额外包装:
class SharedLock implements Lock {
private final Sync sync = new Sync();
<pre class="brush:php;toolbar:false;">private static class Sync extends SimpleSharedLock {
Sync() { super(1); } // 示例:初始 1 个许可
// 可复用上面定义的 tryAcquireShared / tryReleaseShared
}
public void lock() {
sync.acquireShared(1); // 阻塞直到获取成功
}
public void unlock() {
sync.releaseShared(1);
}
// 其他 Lock 方法(newCondition、lockInterruptibly 等)按需补充}
调用 acquireShared 或 releaseShared 即可触发 AQS 的完整流程(检查、入队、阻塞、唤醒、传播)。
关键细节与避坑提示
开发中容易忽略但影响正确性的几点:
- state 的含义必须自洽:它是唯一共享状态,所有操作都基于它,比如用低 16 位存读锁计数、高 16 位存写锁状态,需自行位运算隔离;
-
tryReleaseShared 必须返回 boolean:返回
true才会触发 AQS 的doReleaseShared,进而唤醒等待中的共享节点; -
避免在同步方法中调用阻塞操作:AQS 的 acquire/release 系列方法本身已处理阻塞逻辑,不要在
tryAcquireShared里手动wait或LockSupport.park; -
可重入共享锁需额外记录持有者信息:纯 AQS 不维护线程身份,若需支持同一线程多次获取(如读锁重入),得用
ThreadLocal或Map<thread integer></thread>辅助管理,state 仅表示总许可或计数。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











