AbstractQueuedSynchronizer
目录
- AQS是什么
- AQS什么样
- 内部类
- 成员变量
- 方法public
- 如果不使用AQS会怎样
- AQS的应用
- ReentrantLock
- Sync
- NonfairSync
- FairSync
- 其他实现
AQS是什么
AbstractQueuedSynchronizer(AQS)是Java中的一个并发工具,位于java.util.concurrent.locks包中,用于实现基于锁的同步机制。它是许多同步类(如ReentrantLock和Semaphore等)的基础,并提供了一种用于实现独占锁(exclusive locks)和共享锁(shared locks)等同步机制的框架。
AQS是一个抽象类,它通过维护一个等待队列来管理线程的同步状态。它的主要设计思想是,当某个线程尝试获取锁时,如果锁不可用,该线程会被放入等待队列,然后被阻塞。当锁释放时,AQS会从等待队列中唤醒适当的线程,使其能够竞争锁。
AQS什么样
内部类
| 类名 | 作用 |
|---|---|
| Node | Node类表示等待队列中的一个节点,用于构建等待队列、实现线程的阻塞与唤醒,以及表示等待线程。 |
| ExclusiveNode | ExclusiveNode是Node类的子类,表示独占模式(exclusive mode)下的节点,用于独占锁的等待队列。 |
| SharedNode | SharedNode是Node类的子类,表示共享模式(shared mode)下的节点,用于共享锁的等待队列。 |
| ConditionNode | ConditionNode是Node类的子类,表示条件等待队列中的节点,用于支持条件变量的等待和唤醒机制。 |
| ConditionObject | ConditionObject是AbstractQueuedSynchronizer的内部类,用于实现条件变量,允许线程等待特定条件。 |
这些内部类在AbstractQueuedSynchronizer的实现中扮演着不同的角色,从构建等待队列、表示等待线程、实现条件等待机制,到支持不同模式的锁等待。通过这些内部类的使用,AQS能够支持各种同步场景和锁的实现,从而实现多线程的协调和同步。
成员变量
先看看AQS里都有哪些成员变量:
当然,我可以为您解释这些成员变量的作用。以下是您列出的成员变量的简要解释和作用的表格展示:
| 变量名 | 变量类型 | 变量作用 |
|---|---|---|
| WAITING | int | 表示线程处于等待状态,即等待获取锁。 |
| CANCELLED | int | 表示线程在等待队列中等待时被取消,即等待被中断或其他原因取消。 |
| COND | Node | 一个特殊的标识,用于表示等待队列中的节点是一个条件等待节点而不是独占或共享模式的节点。 |
| head | Node | 等待队列中的头节点,即队列中等待时间最长的节点。 |
| tail | Node | 等待队列中的尾节点,即队列中等待时间最短的节点。 |
| state | int | 表示同步状态的变量,可以是任意整数值,根据具体实现的需要来表示不同的状态。 |
| U | Unsafe | 提供了一些底层的操作,允许直接对内存进行操作,用于实现一些底层同步原语。 |
| STATE | long | 一个偏移量,用于表示在AbstractQueuedSynchronizer类中用于操作state变量的偏移量。 |
| HEAD | long | 一个偏移量,用于表示在AbstractQueuedSynchronizer类中用于操作head变量的偏移量。 |
| TAIL | long | 一个偏移量,用于表示在AbstractQueuedSynchronizer类中用于操作tail变量的偏移量。 |
这些成员变量在AbstractQueuedSynchronizer中用于维护等待队列、线程状态和同步状态等信息,从而实现了基于队列的线程同步和协调机制。不同的变量在整个机制中扮演着不同的角色,以实现正确的多线程同步行为。
方法public
我们来看一下AQS都提供了哪些方法
| 方法名 | 参数含义 | 方法作用 |
|---|---|---|
| acquire | int arg:请求获取锁的参数 | 尝试获取锁,如果获取不到则将调用线程置于阻塞状态,直到锁可用或线程被中断。 |
| acquireInterruptibly | int arg:请求获取锁的参数 | 类似于acquire,但是允许线程在等待锁的过程中被中断。如果线程在等待时被中断,会抛出InterruptedException异常。 |
| tryAcquireNanos | int arg:请求获取锁的参数,long nanosTimeout:等待时间 | 尝试获取锁,但最多等待指定的时间。如果在超时前未能获取锁,则返回结果指示是否成功获取。 |
| release | int arg:释放锁的参数 | 释放锁,通常在获取锁成功后调用。释放锁会唤醒等待队列中的其他线程,使其有机会竞争锁。 |
| acquireShared | int arg:请求获取共享锁的参数 | 类似于acquire,但是用于共享锁的获取。多个线程可以同时获取共享锁,而不像独占锁一样只能有一个线程持有。 |
| acquireSharedInterruptibly | int arg:请求获取共享锁的参数 | 类似于acquireShared,但是允许线程在等待共享锁的过程中被中断。如果线程在等待时被中断,会抛出InterruptedException异常。 |
| tryAcquireSharedNanos | int arg:请求获取共享锁的参数,long nanosTimeout:等待时间 | 类似于tryAcquireNanos,但是用于共享锁的获取。 |
| releaseShared | int arg:释放共享锁的参数 | 释放共享锁,通常在获取共享锁成功后调用。释放共享锁会唤醒等待队列中的其他线程,使其有机会竞争锁。 |
| hasQueuedThreads | - | 判断是否有线程在等待队列中等待获取锁。 |
| hasContended | - | 判断是否有线程在竞争锁。 |
| getFirstQueuedThread | - | 获取等待队列中的第一个线程,但不移除。 |
| isQueued | Thread thread:要检查的线程 | 判断指定线程是否在等待队列中等待获取锁。 |
| apparentlyFirstQueuedIsExclusive | - | 判断等待队列中的第一个线程是否为独占模式(exclusive mode)线程。 |
| hasQueuedPredecessors | - | 判断调用线程是否有在等待队列中的前驱线程。如果有前驱线程,则可能需要执行阻塞操作。 |
| getQueueLength | - | 获取等待队列中的线程数。 |
| getQueuedThreads | - | 获取在等待队列中等待获取锁的所有线程。 |
| getExclusiveQueuedThreads | - | 获取在等待队列中等待获取独占锁的所有线程。 |
| getSharedQueuedThreads | - | 获取在等待队列中等待获取共享锁的所有线程。 |
| toString | - | 返回对象的字符串表示,通常包括等待队列中的线程信息。 |
| owns | Thread thread:要检查的线程 | 判断指定线程是否是当前持有锁的线程。 |
| hasWaiters | - | 判断是否有线程在等待队列中等待释放锁。 |
| getWaitQueueLength | - | 获取等待队列中等待释放锁的线程数。 |
| getWaitingThreads | Condition condition:相关的条件 | 获取与指定条件相关的等待线程列表。 |
这些方法是AbstractQueuedSynchronizer类的核心方法,用于实现多线程同步和协调。
如果不使用AQS会怎样
AQS的应用
我们来直接举个例子
ReentrantLock
ReentrantLock中有3个内部类

Sync
AQS的子类,其实基本上实现了ReentrentLock的大部分方法,ReentrentLock开放出来的大部分方法其实都是直接调用的Sync里的方法
| 方法名 | 参数含义 | 方法作用 |
|---|---|---|
| tryLock | long timeout, TimeUnit unit | 尝试获取锁,如果锁没有被其他线程持有,则获取锁并返回true,如果在指定的时间内无法获取锁,则返回false。 |
| initialTryLock | - | 作为tryLock的一种形式,是在ReentrantLock的构造函数中使用的,用于初始化锁。 |
| lock | - | 获取锁,如果锁已经被其他线程持有,则当前线程会被阻塞,直到获取到锁。 |
| lockInterruptibly | - | 获取锁,如果锁已经被其他线程持有,允许线程在等待时被中断。如果线程在等待时被中断,会抛出InterruptedException异常。 |
| tryLockNanos | long timeout | 尝试在指定的时间内获取锁,如果锁没有被其他线程持有,则获取锁并返回true。如果在指定的时间内无法获取锁,则返回false。 |
| tryRelease | - | 尝试释放锁。 |
| isHeldExclusively | - | 判断当前线程是否持有独占锁。 |
| newCondition | - | 创建一个新的Condition对象,用于支持条件等待。 |
| getOwner | - | 获取当前持有独占锁的线程,如果没有线程持有锁,返回null。 |
| getHoldCount | - | 获取当前线程持有锁的次数,用于可重入锁的计数。 |
| isLocked | - | 判断锁是否被任何线程持有。 |
NonfairSync
Sync的子类,非公平锁的实现。
| 方法名 | 参数 | 作用 |
|---|---|---|
| initialTryLock | unused | 尝试获取锁,如果获取成功返回true,失败返回false。该方法只在构造方法中调用一次。 |
| tryAcquire | acquires | 独占式尝试获取同步状态。如果获取成功返回true,否则返回false。 |
FairSync
Sync的子类,公平锁的实现
| 方法名 | 参数 | 作用 |
|---|---|---|
| initialTryLock | unused | 尝试获取锁,当等待队列无线程等待并且state为0。不同于NonfairSync,公平锁只有无竞争时才会尝试获取锁。 |
| tryAcquire | acquires | 尝试获取同步状态,如果队列中第一个节点是当前线程就获取成功,不是则失败。 |
FairSync也继承自AQS,但实现了公平的锁获取语义 - 等待时间最长的线程最先获得锁。
这两个类开始起作用是在创建ReentrentLock的时候,这里

其他实现
- CountDownLatch: 用来进行线程之间同步协作,可以实现一个线程等待其他线程完成某件事情之后再执行。
- CyclicBarrier: 用来进行线程之间同步协作,可以实现让一组线程达到一个屏障时被阻塞,直到最后一个线程到达屏障时屏障才会开门,所有被屏障拦截的线程才会继续执行。
- Semaphore: 用于控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。
- Exchanger: 用于进行线程间的数据交换。它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。
- BlockingQueue: 一个支持两个附加操作的队列。在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。
- ForkJoinPool: Fork/Join框架中的线程池实现类,用于异步执行fork/join任务。
相关文章:
AbstractQueuedSynchronizer
目录 AQS是什么AQS什么样内部类成员变量方法public如果不使用AQS会怎样 AQS的应用ReentrantLockSyncNonfairSyncFairSync 其他实现 AQS是什么 AbstractQueuedSynchronizer(AQS)是Java中的一个并发工具,位于java.util.concurrent.locks包中&a…...
谈谈什么是云计算?以及它的应用
作者:Insist-- 个人主页:insist--个人主页 作者会持续更新网络知识和python基础知识,期待你的关注 目录 编辑 一、什么是云计算 二、云计算的优势与劣势? 1、云计算的优势 ①提高资源利用率 ②提升效率 ③降低成本 2、云…...
【BASH】回顾与知识点梳理(十六)
【BASH】回顾与知识点梳理 十六 十六. 十二至十五章知识点总结及练习16.1 总结16.2 练习16.3 简答题 该系列目录 --> 【BASH】回顾与知识点梳理(目录) 十六. 十二至十五章知识点总结及练习 16.1 总结 绝对路径:『一定由根目录 / 写起』…...
docsify gitee 搭建个人博客
docsify & gitee 搭建个人博客 文章目录 docsify & gitee 搭建个人博客1.npm 安装1.1 在Windows上安装npm:1.2 在macOS上安装npm:1.3 linux 安装npm 2. docsify2.1 安装docsify2.2 自定义配置2.2.1 通过修改index.html,定制化开发页面…...
SpringBoot2-Tomcat部署
1.排除内置 Tomcat 在pom.xml文件中的下添加以下代码,用于排除SpringBoot内置Tomcat <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion&…...
Docker查看、创建、进入容器相关的命令
1.查看、创建、进入容器的指令 用-it指令创建出来的容器,创建完成之后会立马进入容器。退出之后立马关闭容器。 docker run -it --namec1 centos:7 /bin/bash退出容器: exit查看现在正在运行的容器命令: docker ps查看历史容器࿰…...
leetcode1. 两数之和
题目:leetcode1. 两数之和 描述: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中…...
温室花卉种植系统springboot框架jsp鲜花养殖智能管理java源代码
本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 基于Git无线传感网络的温室花卉种植智能控制系统 系统…...
测试老鸟经验总结,Jmeter性能测试-重要指标与性能结果分析(超细)
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 Aggregate Report …...
IDEA设置Maven自动编译model
IDEA设置Maven自动编译model 项目工程结构IDEA maven设置 项目工程结构 假设我们的项目结构是下图这样,也就是一个父工程下包含多个子模块,其中dubbo-01-api是公共模块,其它两个模块要想使用必须在pom文件中引入。 本地开发要想不会报错&am…...
关于本地mockjs的使用
安装mockjs npm install mockjs -s在src下新建目录mockData,所有mock请求可以放该文件夹下面。例如在mockData文件夹下新建一个home.js文件。用来处理首页的请求数据 home.js export default {getHomeData:()>{return{code:200,data:{tableData:[{name:张三,se…...
hive 中最常用日期处理函数
hive 常用日期处理函数 在工作中,日期函数是提取数据计算数据必须要用到的环节。哪怕是提取某个时间段下的明细数据也得用到日期函数。今天和大家分享一下常用的日期函数。为什么说常用呢?其实这些函数在数据运营同学手上是几乎每天都在使用的。 技术交…...
记录一下Java实体转json字段顺序问题
特殊需求,和C交互他们那边要求字段顺序要和他们定义的一致(批框架) 如下: Data public class UserDto {private String name;private Integer age;private String addr; }未转换前打印: 转换后打印: 可以看到转换为json顺序打印…...
微积分入门:总结归纳汇总(一)
基础 标准符号约定: ( s i n x ) n (sinx)^n (sinx)...
ubuntu python虚拟环境venv搭配systemd服务实战(禁用缓存下载--no-cache-dir)
文章目录 参考文章目录结构步骤安装venv查看python版本创建虚拟环境激活虚拟环境运行我们程序看缺少哪些依赖库,依次安装它们接下来我们配置python程序启动脚本,脚本中启动python程序前需先激活虚拟环境配置.service文件然后执行部署脚本,成功…...
案例15 Spring Boot入门案例
1. 选择Spring Initializr快速构建项目 2. 设置项目信息 3. 选择依赖 4. 设置项目名称 5. 项目结构 6. 项目依赖 自动配置了Spring MVC、内置了Tomcat、配置了Logback(日志)、配置了JSON。 7. 创建HelloController类 com.wfit.boot.hello目录下创建HelloCo…...
物联网是下一个风口吗?
随着科技的持续进步,物联网行业正在迅速兴起,展现出巨大的潜力。那么,物联网行业的未来是什么样的呢? 1. 5G技术的广泛应用和普及 随着5G技术的快速发展和商业化推广,物联网行业将迎来一个巨大的飞跃。5G技术的高速传…...
8月9日上课内容 nginx反向代理与负载均衡
负载均衡工作当中用的很多的,也是面试会问的很重要的一个点 负载均衡:通过反向代理来实现(nginx只有反向代理才能做负载均衡) 正向代理的配置方法(用的较少) 反向代理的方式:四层代理与七层代…...
易服客工作室:Elementor AI简介 – 彻底改变您创建网站的方式
Elementor 作为领先的 WordPress 网站构建器,是第一个添加本机 AI 集成的。Elementor AI 的第一阶段将使您能够生成和改进文本和自定义代码(HTML、自定义代码和自定义 CSS)。我们还已经在进行以下阶段的工作,其中将包括基于人工智…...
ClickHouse的数据类型
1.整数型 固定长度的整型,包括有符号整型或无符号整型。整型范围(-2n-1~2n-1-1): Int8 - [-128 : 127] Int16 - [-32768 : 32767] Int32 - [-2147483648 : 2147483647] Int64 - [-9223372036854775808 : 9223372036854775807]无符…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...
认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...
02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...
