Java 中并发编程怎么使用 AbstractQueuedSynchronizer 实现自定义同步器

星雪小哥_2585

星雪小哥_2585

2026-08-23

246人浏览

原创

使用aqs实现自定义同步器需继承aqs并重写tryacquire/tryrelease等模板方法,依托state变量、clh队列和独占/共享模式三要素构建线程安全组件。

java 中并发编程怎么使用 abstractqueuedsynchronizer 实现自定义同步器

要使用 AbstractQueuedSynchronizer(AQS)实现自定义同步器,核心是继承 AQS 并重写其关键的模板方法,再基于它封装出线程安全的同步组件(如锁、信号量等)。AQS 本身不直接提供同步语义,而是提供统一的等待队列、状态管理与线程阻塞/唤醒机制。

理解 AQS 的三个核心要素

AQS 围绕以下三部分构建:

  • state 状态变量:用 volatile int 表示,代表同步状态(如 ReentrantLock 中的持有次数、Semaphore 中的剩余许可数)。通过 getState()、setState(int)、compareAndSetState(int, int) 安全操作。
  • CLH 同步队列:一个 FIFO 的双向链表,存储等待获取同步状态的线程节点(Node)。AQS 自动维护该队列,你无需手动操作队列结构。
  • 独占/共享模式的获取与释放逻辑:由子类决定如何解释 state,并实现对应的 tryAcquire、tryRelease(独占)或 tryAcquireShared、tryReleaseShared(共享)方法。

实现一个简单的不可重入独占锁(MyLock)

这是最典型的入门示例,帮助掌握基本骨架:

public class MyLock implements Lock {
    private static class Sync extends AbstractQueuedSynchronizer {
        // 尝试获取独占锁:state == 0 表示空闲,CAS 设为 1
        protected boolean tryAcquire(int acquires) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        // 尝试释放独占锁:仅当当前线程持有时才允许释放
        protected boolean tryRelease(int releases) {
            if (getState() == 0) throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
    }

    private final Sync sync = new Sync();

    public void lock() {
        sync.acquire(1); // 调用 AQS 的 acquire,内部会调用 tryAcquire
    }

    public void unlock() {
        sync.release(1); // 调用 AQS 的 release,内部会调用 tryRelease
    }

    // 其他接口方法(如 newCondition、lockInterruptibly 等)可按需补充
}

注意:acquire(1) 和 release(1) 中的参数只是约定俗成的“数量”,对本例无实际意义(因不可重入),但必须与 tryAcquire/tryRelease 的参数匹配。

Java Maven Code Review
Java Maven Code Review

审查Java Maven项目(ZIP压缩包或GitLab仓库URL),检查代码规范、命名、模块边界、可维护性问题以及重复代码。

下载

处理可重入、条件等待等进阶能力

若需支持可重入,state 应表示重入次数;若需 Condition,需在 Sync 内部使用 newCondition() 创建条件队列(AQS 提供默认实现):

  • 可重入逻辑:在 tryAcquire 中先检查当前线程是否已持有锁(getExclusiveOwnerThread() == current),是则 state += 1;否则尝试 CAS 获取。
  • 条件等待:Sync 类需继承 AQS 并实现 isHeldExclusively()(判断当前是否独占持有),然后调用 sync.newCondition() 返回 ConditionObject 实例。await/signal 由 AQS 自动调度到条件队列和同步队列之间转移节点。
  • 中断敏感获取:用 acquireInterruptibly(1) 替代 acquire(1),使 lock() 可响应中断。

避免常见错误

初学者容易踩的坑包括:

  • 忘记设置/清除 owner 线程:独占模式下,setExclusiveOwnerThread 和置 null 必须严格配对,否则 isHeldExclusively 或可重入判断失效。
  • tryRelease 返回 false 却未改变 state:AQS 要求 tryRelease 成功时返回 true,失败返回 false;若返回 false,AQS 会认为释放失败并抛异常。
  • 在非 volatile 或非 CAS 场景修改 state:所有对 state 的修改必须通过 AQS 提供的原子方法,否则破坏可见性与原子性。
  • 在同步器外部直接操作 AQS 方法:不要在 MyLock 外暴露 sync 对象或直接调用其 protected 方法,应严格通过 public 接口封装。

不复杂但容易忽略:AQS 是构建同步组件的“底盘”,真正难的是根据业务语义正确定义 state 含义、设计公平/非公平策略、处理超时、中断、取消等边界情况。从不可重入锁起步,逐步叠加功能,比一上来就写复杂同步器更稳妥。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

9597

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

6742

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

5972

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1044

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

868

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1276

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2509

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

19851

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1135

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习