深入理解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,一种设计优雅的神经网络架构。 通过避免…...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
macOS 终端智能代理检测
🧠 终端智能代理检测:自动判断是否需要设置代理访问 GitHub 在开发中,使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新,例如: fatal: unable to access https://github.com/ohmyzsh/oh…...
Linux-进程间的通信
1、IPC: Inter Process Communication(进程间通信): 由于每个进程在操作系统中有独立的地址空间,它们不能像线程那样直接访问彼此的内存,所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...
Tauri2学习笔记
教程地址:https://www.bilibili.com/video/BV1Ca411N7mF?spm_id_from333.788.player.switch&vd_source707ec8983cc32e6e065d5496a7f79ee6 官方指引:https://tauri.app/zh-cn/start/ 目前Tauri2的教程视频不多,我按照Tauri1的教程来学习&…...
RabbitMQ 各类交换机
为什么要用交换机? 交换机用来路由消息。如果直发队列,这个消息就被处理消失了,那别的队列也需要这个消息怎么办?那就要用到交换机 交换机类型 1,fanout:广播 特点 广播所有消息:将消息…...
标注工具核心架构分析——主窗口的图像显示
🏗️ 标注工具核心架构分析 📋 系统概述 主要有两个核心类,采用经典的 Scene-View 架构模式: 🎯 核心类结构 1. AnnotationScene (QGraphicsScene子类) 主要负责标注场景的管理和交互 🔧 关键函数&…...
