【并发编程JUC】AQS详解
定义理解
AQS,全称为AbstractQueuedSynchronizer,是Java并发包(java.util.concurrent)中的一个框架级别的工具类,用于构建锁和同步器。它是许多同步类的基础,如ReentrantLock、Semaphore、CountDownLatch等,都是通过实现AQS的模板方法来实现其内部同步逻辑的。
- 同步状态:AQS使用一个volatile int类型的变量来表示同步状态,通过内置的FIFO(先进先出)队列(也称为CLH队列,一个虚拟的双向队列)来完成获取资源线程的排队工作。这个状态变量是线程共享的,用于表示同步资源的状态。
- CLH队列:CLH(Craig, Landin, and Hagersten)队列是AQS内部用于管理等待获取同步状态的线程的队列。它是一个虚拟的双向队列,即不存在队列实例,仅存在节点之间的关联关系。每个等待获取锁的线程都被封装成一个队列的节点(Node)。(将没有获取锁的线性封装成节点)
理解锁和同步器的关系
- 锁(Lock):锁是面向使用者的,它定义了使用者与锁交互的接口,比如允许两个线程并行访问某个资源,但隐藏了实现细节。锁是一个更高级的同步机制,它提供了比synchronized关键字更丰富的功能和灵活性。常见的锁实现有ReentrantLock等。
- 同步器(AbstractQueuedSynchronizer, AQS):同步器是面向锁的实现者的,它简化了锁的实现方式,屏蔽了同步状态管理、线程的排队、等待与唤醒等底层操作。同步器是构建锁和其他同步组件的基础框架,通过提供一套模板方法,使得开发者能够轻松地实现自定义的同步逻辑。
- 锁的实现依赖于同步器:在锁的实现中,通常会聚合同步器(AQS)来实现锁的语义。同步器为锁提供了必要的同步机制,如线程的排队、等待与唤醒等,从而简化了锁的实现复杂度。
AQS结构
梳理结构
- Lock是Java并发包(java.util.concurrent.locks)中的一个接口
- ReentrantLock是Lock接口的一个具体实现,它提供了可重入的互斥锁。
- Sync是ReentrantLock中的一个内部抽象类,它继承自AbstractQueuedSynchronizer(AQS)。
- FairSync是ReentrantLock中的一个内部类,它继承自Sync类。
- NonfairSync同样是ReentrantLock的一个内部类,也继承自Sync类
- AQS是Java并发包中的一个基础类,用于构建同步器(如锁和其他同步组件)。
Lock接口定义了锁的基本行为;ReentrantLock是Lock接口的一个具体实现,提供了可重入的互斥锁;Sync是ReentrantLock的内部抽象类,用于提供锁的基本实现机制;FairSync和NonfairSync是Sync的两个子类,分别实现了公平锁和非公平锁的逻辑;AQS则是ReentrantLock等同步器实现同步功能的基础。这些组件共同构成了Java并发包中强大的锁机制。
非公平锁源码如下:
公平锁源代码如下:
在非公平锁中,由于新到来的线程有可能直接尝试获取锁(而不需要排队),因此唤醒机制需要灵活处理。
模拟示例
假设有三个线程A、B、C都试图获取同一个ReentrantLock的锁(该锁以非公平模式配置)。
线程A的行为
- 尝试获取锁:线程A首先调用lock()方法,该方法内部会尝试通过compareAndSetState(0, 1)将锁的状态从0(未锁定)更改为1(锁定)。如果当前没有其他线程持有锁(即锁状态为0),则线程A成功获取锁。
- 执行业务逻辑:线程A在获取锁之后执行其业务逻辑。
线程B和C的行为(几乎同时)
当线程A持有锁时,线程B和C尝试获取锁。
- 调用acquire(1):线程B和C都调用acquire(1)方法,该方法是非公平锁获取锁的主要入口。
- 尝试非公平获取锁:acquire(1)内部调用tryAcquire(1),进而调用nonfairTryAcquire(1)。nonfairTryAcquire(1)首先检查当前锁状态是否为0(即未锁定),如果是,则尝试通过compareAndSetState(0, 1)获取锁。但由于线程A已经持有锁,所以B和C的这一步都会失败。(如果占用线程和当前线性为同一线程时,即为可重入锁)
- 添加等待者:由于nonfairTryAcquire(1)返回false,线程B和C都会调用addWaiter()方法将自己封装成一个节点(Node),并通过enq(node)方法将节点加入到等待队列中。如果队列为空(即还没有其他线程在等待),则初始化头节点(head)并设置尾节点(tail)为新加入的节点。否则,将新节点添加到队尾。
- 进入等待队列并等待:线程B和C在加入等待队列后,会调用acquireQueued(node, 1)方法。在这个方法中,线程会进入一个自旋循环,不断检查前驱节点的状态,并尝试通过park()方法使自己进入等待状态(阻塞)。如果前驱节点的状态是SIGNAL(-1),则线程会通过LockSupport.park(this)被阻塞,直到被唤醒。
线程A释放锁
- 释放锁:当线程A完成其业务逻辑后,会调用unlock()方法来释放锁。这会将锁的状态从1改回0,并唤醒等待队列中的一个线程(如果有的话)。
- 唤醒等待线程:在释放锁的过程中,unlock()方法会调用LockSupport.unpark(thread)来唤醒等待队列中的一个线程。由于是非公平锁,被唤醒的线程不一定是等待时间最长的线程(即队列的头部线程)。
线程B或C被唤醒
被唤醒的线程(可能是B也可能是C,这取决于线程调度器的决策)会重新进入acquireQueued(node, 1)方法的自旋循环,并再次尝试获取锁。如果此时锁已被释放(即状态为0),则该线程可能会成功获取锁并退出自旋循环,继续执行其业务逻辑。
相关文章:

【并发编程JUC】AQS详解
定义理解 AQS,全称为AbstractQueuedSynchronizer,是Java并发包(java.util.concurrent)中的一个框架级别的工具类,用于构建锁和同步器。它是许多同步类的基础,如ReentrantLock、Semaphore、CountDownLatch等…...

如何找BMS算法、BMS软件的实习
之前一直忙,好久没有更新了,今天就来写一篇文章来介绍如何找BMS方向的实习,以及需要具备哪些条件,我的实习经历都是在读研阶段找的,读研期间两段的实习经历再加上最高影响因子9.4分的论文,我的秋招可以说是…...

AR视频技术与EasyDSS流媒体视频管理平台:打造沉浸式视频体验
随着增强现实(AR)技术的飞速发展,其在各个领域的应用日益广泛。这项技术通过实时计算摄影机影像的位置及角度,将虚拟信息叠加到真实世界中,为用户带来超越现实的感官体验。AR视频技术不仅极大地丰富了我们的视觉体验&a…...
每天一个数据分析题(三百九十九)- 逻辑回归
逻辑回归中,若选0.5作为阈值区分正负样本,其决策平面是( ) A. wxb= 0 B. wxb= 1 C. wxb= -1 D. wxb= 2 数据分析认证考试介绍:点击进入 题目来源于CDA模拟题库 点…...
【ARMv8/v9 GIC 系列 5.2 -- GIC 分组介绍:Group 0 |Group 1| Non-Secure Group 1】
请阅读【ARM GICv3/v4 实战学习 】 文章目录 GIC Interrupt grouping中断分组配置寄存器GIC 中断分组介绍Group 0(安全组0)Group 1(安全组1)Non-Secure Group 1(非安全组1)总结及例子GIC Interrupt grouping ARM GICv3 通过中断分组机制,与ARMv8异常模型和安全模型进行…...
前端代码规范 - 日志打印规范
在前端开发中,随着项目迭代升级,日志打印逐渐风格不一,合理的日志输出是监控应用状态、调试代码和跟踪用户行为的重要手段。一个好的日志系统能够帮助开发者快速定位问题,提高开发效率。本文将介绍如何在前端项目中制定日志输出规…...

C# 类型转换之显式和隐式
文章目录 1、显式类型转换2. 隐式类型转换3. 示例4. 类型转换的注意事项5. 类型转换的应用示例总结 在C#编程中,类型转换是一个核心概念,它允许我们在程序中处理不同类型的数据。类型转换可以分为两大类:显式类型转换(Explicit Ca…...

Ubuntu多显示器设置不同缩放比例
Ubuntu多显示器设置不同缩放比例 设备问题解决方案 设备 笔记本屏幕分辨率为2560 \times 1600,外接显示器的分辨率为3840 \times 2160。 问题 Ubuntu默认的显示器设置中,缩放仅能选择100%,200%,300%,400%。假…...

以太网协议介绍——UDP
注:需要先了解一些以太网的背景知识,方便更好理解UDP协议、 以太网基础知识一 以太网基础知识二 UDP协议 UDP即用户数据报协议,是一种面向无连接的传输层协议,属于 TCP/IP 协议簇的一种。UDP具有消耗资源少、通信效率高等优点&a…...
FFMpeg rtmp 无压缩推送本地yuv文件 压缩推送本地yuv文件
可以借鉴的:C使用FFmpeg实现YUV数据编码转视频文件_C 语言_脚本之家 yuv文件下载地址:YUV Sequences 无压缩的方式推送本地yuv文件 代码: #include <stdio.h> #include <unistd.h> #include <iostream> extern "C&…...
PostgreSQL LIMIT 子句
PostgreSQL LIMIT 子句 PostgreSQL 是一种功能强大的开源对象关系数据库管理系统,广泛用于各种应用中。在处理大量数据时,我们通常只需要检索部分记录,而不是整个数据集。这时,LIMIT 子句就变得非常有用。本文将详细介绍 Postgre…...

误删分区后的数据拯救:双管齐下恢复策略
在数字化时代,数据的价值日益凸显,而误删分区作为常见的数据安全威胁之一,常常让用户措手不及。本文将深入探讨误删分区的现象,并为您揭示两种高效的数据恢复方案,旨在帮助您在最短时间内找回失去的数据,同…...
git 添加本地分支, clean
//以develop为源创建本地分支fromdevelop git checkout -b fromdevelop git add . git commit -m "local" git checkout -b local/dev //切换到远程分支. git checkout dev git clean_git clean -f -d-CSDN博客 git clean -f -d #删除当前目录下没有被track…...

Linux:进程间通信(一.初识进程间通信、匿名管道与命名管道、共享内存)
上次结束了基础IO:Linux:基础IO(三.软硬链接、动态库和静态库、动精态库的制作和加载) 文章目录 1.认识进程间通信2.管道2.1匿名管道2.2pipe()函数 —创建匿名管道2.3匿名管道的四种情况2.4管道的特征 3.基于管道的进程池设计4.命…...
QML-各类布局
Colunm布局 Column{id:colspacing: 30Repeater{id:repmodel: ListModel{}Button{width: 100height: 50text: "btn"index}}//开始时候移动move: Transition {NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce }}//添加时变化add:Transi…...

el-table封装点击列筛选行数据功能,支持筛选,搜索,排序功能
数据少的话,可以前端实现,如果多的话,建议还是请求接口比较合理父组件: <template> <div class"home"> <!-- <img alt"Vue logo" src"../assets/logo.png"> <HelloWorld …...

【SpringBoot3学习 | 第1篇】SpringBoot3介绍与配置文件
文章目录 前言 一. SpringBoot3介绍1.1 SpringBoot项目创建1. 创建Maven工程2. 添加依赖(springboot父工程依赖 , web启动器依赖)3. 编写启动引导类(springboot项目运行的入口)4. 编写处理器Controller5. 启动项目 1.2 项目理解1. 依赖不需要写版本原因2. 启动器(Starter)3. Sp…...

SpringBoot整合Dubbo的快速使用教程
目录 一、什么是Dubbo? 二、SpringBoot整合Dubbo 1、父工程引入依赖 2、各个Dubbo服务子模块引入依赖 3、服务提供者 (1)启动类添加注解EnableDubbo (2)服务类添加注解DubboService (3)配置文件…...
昇思25天学习打卡营第12天| 基于MindNLP+MusicGen生成自己的个性化音乐
之前都是看图文类的东西,今天体验一点不一样的。来点听力的内容。 mindspore有音乐生成模型MusicGen,MusicGen支持两种生成模式:贪心(greedy)和采样(sampling)。在实际执行过程中,采…...

代理设计模式和装饰器设计模式的区别
代理设计模式: 作用:为目标(原始对象)增加功能(额外功能,拓展功能) 三种经典应用场景: 1:给原始对象增加额外功能(spring添加事务,Mybatis通过代理实现缓存功能等等) 2:远程代理(网络通信,输出传输(RPC,D…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...

群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...
node.js的初步学习
那什么是node.js呢? 和JavaScript又是什么关系呢? node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说, 需要在node.js的环境上进行当JavaScript作为前端开发语言来说,需要在浏览器的环境上进行 Node.js 可…...

动态规划-1035.不相交的线-力扣(LeetCode)
一、题目解析 光看题目要求和例图,感觉这题好麻烦,直线不能相交啊,每个数字只属于一条连线啊等等,但我们结合题目所给的信息和例图的内容,这不就是最长公共子序列吗?,我们把最长公共子序列连线起…...
FTXUI::Dom 模块
DOM 模块定义了分层的 FTXUI::Element 树,可用于构建复杂的终端界面,支持响应终端尺寸变化。 namespace ftxui {...// 定义文档 定义布局盒子 Element document vbox({// 设置文本 设置加粗 设置文本颜色text("The window") | bold | color(…...