深入理解AQS:Java并发编程中的核心组件
目录
- AQS简介
- AQS的设计思路
- AQS的核心组成部分
- 状态(State)
- 同步队列(Sync Queue)
- 条件队列(Condition Queue)
- AQS的内部实现
- 节点(Node)
- 锁的获取与释放
- 独占锁
- 共享锁
- 条件变量
- AQS的应用案例
- ReentrantLock
- CountDownLatch
- Semaphore
- 总结
- 参考文献
AQS简介
AbstractQueuedSynchronizer(AQS)是Java并发包(java.util.concurrent)中用于构建锁和同步器的基础框架。AQS通过一个FIFO(First In First Out)等待队列来管理获取锁的线程,提供了独占模式和共享模式两种同步方式。
AQS的设计目标是简化开发人员在实现自定义同步器时的复杂性。通过继承AQS并实现其抽象方法,开发人员可以轻松创建功能强大的同步器。
AQS的设计思路
AQS的设计基于两个关键思想:
- 状态管理:使用一个volatile类型的整数变量来表示同步状态,通过CAS操作(Compare And Swap)来更新状态。
- 队列管理:使用一个FIFO队列来管理等待获取锁的线程。
这种设计方式使得AQS既能保证线程的安全性,又能提供高效的性能。
AQS的核心组成部分
状态(State)
AQS通过一个整数变量来表示同步状态。这个变量可以表示不同的含义,例如:
- 对于独占锁,0表示未锁定,1表示已锁定。
- 对于共享锁,可以表示当前可用的资源数量。
状态变量通过volatile关键字修饰,确保其在多个线程之间的可见性。
同步队列(Sync Queue)
同步队列是一个FIFO队列,当线程无法获取锁时,它们会被加入到该队列中。队列中的每个节点都表示一个等待的线程。
条件队列(Condition Queue)
条件队列用于管理那些调用了条件变量的await方法后进入等待状态的线程。条件队列与同步队列类似,都是FIFO队列。
AQS的内部实现
节点(Node)
AQS的队列是由Node节点组成的。每个Node节点包含以下几个重要字段:
- thread:表示当前节点所代表的线程。
- nextWaiter:用于条件队列,指向下一个等待的节点。
- waitStatus:表示节点的等待状态。
Node节点的等待状态包括:
- CANCELLED:节点已取消。
- SIGNAL:节点需要唤醒。
- CONDITION:节点在条件队列中等待。
- PROPAGATE:下一个acquireShared需要无条件传播。
锁的获取与释放
独占锁
独占锁意味着一次只能有一个线程持有锁。独占锁的获取与释放通过以下方法实现:
acquire(int arg):尝试获取独占锁,如果失败则加入同步队列。release(int arg):释放独占锁,成功后唤醒同步队列中的下一个节点。
独占锁的获取逻辑主要通过tryAcquire方法实现,开发人员需要重写该方法来定义锁的获取规则。
共享锁
共享锁允许多个线程同时持有锁。共享锁的获取与释放通过以下方法实现:
acquireShared(int arg):尝试获取共享锁,如果失败则加入同步队列。releaseShared(int arg):释放共享锁,成功后唤醒同步队列中的下一个节点。
共享锁的获取逻辑主要通过tryAcquireShared方法实现,开发人员需要重写该方法来定义锁的获取规则。
条件变量
AQS还提供了条件变量的支持,通过ConditionObject类来实现。条件变量的核心方法包括:
await():当前线程进入等待状态,加入条件队列。signal():唤醒条件队列中的一个节点。signalAll():唤醒条件队列中的所有节点。
条件变量的实现依赖于Node节点的CONDITION状态。当线程调用await方法时,节点会被加入到条件队列,并将其状态设置为CONDITION。
AQS的应用案例
ReentrantLock
ReentrantLock是一种可重入的独占锁,它通过继承AQS并实现其抽象方法来实现锁的功能。主要包括以下几个步骤:
- 实现
tryAcquire方法:定义独占锁的获取逻辑。 - 实现
tryRelease方法:定义独占锁的释放逻辑。 - 使用同步队列来管理等待的线程。
CountDownLatch
CountDownLatch是一种同步工具类,它允许一个或多个线程等待直到其他线程执行完毕。它也基于AQS实现,主要包括以下步骤:
- 实现
tryAcquireShared方法:定义共享锁的获取逻辑。 - 实现
tryReleaseShared方法:定义共享锁的释放逻辑。 - 使用一个计数器来表示需要等待的线程数量。
Semaphore
Semaphore是一种计数信号量,它允许多个线程访问一定数量的共享资源。它的实现步骤与CountDownLatch类似:
- 实现
tryAcquireShared方法:定义共享锁的获取逻辑。 - 实现
tryReleaseShared方法:定义共享锁的释放逻辑。
总结
AbstractQueuedSynchronizer(AQS)是Java并发包中的核心组件,为实现锁和其他同步器提供了基础框架。通过管理同步状态和等待队列,AQS能够高效地处理多线程并发问题。开发人员可以通过继承AQS并实现其抽象方法,轻松创建自定义的同步器。
本文详细介绍了AQS的概念、设计思路、核心组成部分及其内部实现机制,并通过ReentrantLock、CountDownLatch和Semaphore的案例展示了AQS在实际应用中的使用方法。理解AQS的工作原理对于掌握Java并发编程至关重要。
参考文献
- Doug Lea, “A Scalable Synchronization Mechanism for Java”
- Java Concurrency in Practice
- Java官方文档
- Java并发编程的艺术
通过本文的详细讲解,希望读者能够深入理解AQS的工作原理,并能够在实际编程中灵活运用这一强大的工具。
相关文章:
深入理解AQS:Java并发编程中的核心组件
目录 AQS简介AQS的设计思路AQS的核心组成部分 状态(State)同步队列(Sync Queue)条件队列(Condition Queue) AQS的内部实现 节点(Node)锁的获取与释放 独占锁共享锁 条件变量 AQS的应…...
集合进阶:List集合
一.List集合的特有方法 1.Collection的方法List都继承了 2.List集合因为有索引,所以多了很多索引操作的方法。 3.add // 1.创建一个集合List<String> list new ArrayList<>(); // 2.添加元素list.add("aaa");list.add("bbb"…...
el-table表头修改文字或者背景颜色,通过header-row-style设置样式
方式一 <el-table :header-cell-style"{text-align: center}" />方式二 <template><el-table :header-cell-style"tableHeaderColor" /> </template> <script> export default {methods: {tableHeaderColor ({row, column…...
web前端-CSS
CSS CSS概述: CSS是Cascading Style Sheets(级联样式表),是一种样式表语言,用于控制网页布局,外观(比如背景图片,图片高度,文本颜色,文本字体,高级定位等等) 可将页面的内容与样式分离开,样式放于单独的.css文件或者HTML某处 CSS是网页样式,HTML是网页…...
u8g2 使用IIC驱动uc1617 lcd 字符显示只显示上半部分,不显示下半部
使用u8g2 使用硬件iic驱动某些page为4个字节 带灰度的lcd显示屏幕的时候有时候只显示上半部,下半部不显示,例如uc1617等。 原因: 以uc1617为例,链接https://github.com/olikraus/u8g2/blob/master/csrc/u8x8_d_uc1617.c 在u8x8_d_uc1617_common方法中的case U8X8_MSG_DI…...
单片机第五季-第八课:STM32CubeMx和FreeRTOS
1,FreeRTOS背景介绍 RTOS简介: 实时操作系统,本用于追求实时性的嵌入式系统,典型:ucos/uclinux/vxworks; 特点:中断响应快、一般可嵌套中断、使用实地址、多任务; (实…...
【Linux】进程控制1——进程创建和进程终止
1.进程创建 1.1.再谈fork 在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。 #include <unistd.h> pid_t fork(void);//pid_t为整形 返回值:子进程中的fork()返回0ÿ…...
计算机图形学入门16:曲线
1.曲线 曲线(Curves)在图形学中应用非常广泛,比如:相机的拍摄路径、物体的移动路径、动画曲线、矢量字体等。如下图所示,是使用曲线到矢量字体的应用,通过移动一些控制点来改变字体。 2.贝塞尔曲线 2.1 贝…...
【Ruby基础01】windows和termux中搭建Ruby开发环境
windows下环境搭建 railsinstaller官方git地址 按照文档安装git、nodejs、yarn,安装教程百度一下。railsinstall可以从release页面下载最新版本4.1.0。 安装完成如下 安装RubyMine 下载RubyMine RubyMine下载地址 安装激活 下载文件,按照里面的流程…...
2406c++,iguana动态反射
原文 iguana是一个基于编译期反射的序化库,支持从结构序化到不同数据格式. iguana可序化一个C结构到json,xml,yaml和protobuf格式.这都是通过编译期反射实现的. 现在iguana也支持了动态反射,主要特征: 1,通过对象名创建对象实例 2,取对象所有字段名 3,根据字段名取字段值 4,根…...
干货分享——AB站帮你解决独立站收款难题
目前,国内已经有抖音、拼多多和淘宝平台推出“仅退款”售后服务,无疑是加剧了原本就在疯狂打价格战的国内电商的严峻现状,使得商家不得不担心被顾客“薅羊毛”。在国内电商环境严重“内卷”的情况下,拓宽海外市场不失为一大妙计。…...
C++继承与派生
1.基本知识 类的继承是新类从已有类那里获得特性,从已有的类产生新类的过程称为类的派生; 已有类称为基类或父类,派生出的新类则称为派生类或子类; 继承的功能: (1)使得基类与派生类之间建立…...
Survival Animations
一套生存游戏的动画集,包括采集、建造、捕鱼、剥皮/鞣制、篝火等更多内容。 总动画数:89 建造/制作 30 篝火 28 饮水 3 水壶 3 觅食 2 治疗 3 空闲 1 原始捕鱼 7 剥皮 1 矛捕鱼 4 伐木 5 下载:Unity资源商店链接资源下载链接 效果图:...
Cargo 教程
Cargo 教程 1. 引言 Cargo 是 Rust 编程语言的包管理器和构建工具。它为 Rust 项目提供了依赖管理、编译和打包等功能。本教程将详细介绍 Cargo 的基本用法,帮助您快速上手 Rust 项目开发。 2. 安装 Cargo 在开始使用 Cargo 之前,您需要确保已经安装了 Rust 编程语言。Ru…...
linux中“PXE高效批量装机”
在大规模的 Linux 应用环境中,如 Web 群集、分布式计算等,服务器往往并不配备光驱设备,在这种情况下,如何为数十乃至上百台服务器裸机快速安装系统呢?传统的 USB光驱、移动硬盘等安装方法显然已经难以满足需求。 PXE …...
emm, ComfyUI的作者从Stability.AI离职了
🍖背景 今天在更新ComfyUI的过程中,看到Manager中有这样一段描述: 嗯?做了新的官方网站?然后开始新篇章? 难道说ComfyUI的作者从Stability.AI离职了? 赶紧点开链接看了下,emm&…...
Redis-五种数据结构之列表(ziplist、quicklist)
列表 文章目录 列表压缩列表-ziplistziplist 定义级联更新 快速列表-quicklistquicklistNode 定义quicklist 定义quicklist常用操作其他操作quicklist 相对于普通链表优点quick应用场景在redis 中使用quicklist 列表数据类型可以存储一组按插入顺序排序的字符串,他很…...
记一次全设备通杀未授权RCE的挖掘经历
想来上一次挖洞还在一年前的大一下,然后就一直在忙活写论文,感觉挺枯燥的(可能是自己不太适合弄学术吧QAQ),所以年初1~2月的时候,有空的时候就又会挖一挖国内外各大知名厂商的设备,拿了几份思科…...
【数据库编程-SQLite3(一)】sqlite3数据库在Windows下的配置及测试
学习分析 1、资源准备2、环境配置2.1、将资源包下载解压缩保存。2.2、在QT中创建工程,配置环境 3、测试配置3.1、 sqlite3_open函数3.2、sqlite3_close函数3.3、代码测试 1、资源准备 资源包 2、环境配置 2.1、将资源包下载解压缩保存。 解压缩得到以下文件 2.2、在QT中创建…...
YOLOv10改进 | 主干篇 | YOLOv10引入华为VanillaNet替换Backbone
1. VanillaNet介绍 1.1 摘要: 基础模型的核心是“越多越好”的理念,计算机视觉和自然语言处理领域取得的惊人成功就是例证。 然而,优化的挑战和变压器模型固有的复杂性要求范式向简单性转变。 在这项研究中,我们介绍了 VanillaNet,一种设计优雅的神经网络架构。 通过避免…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
