【并发编程JUC】AQS详解

news2024/11/27 11:50:38

定义理解

AQS,全称为AbstractQueuedSynchronizer,是Java并发包(java.util.concurrent)中的一个框架级别的工具类,用于构建锁和同步器。它是许多同步类的基础,如ReentrantLock、Semaphore、CountDownLatch等,都是通过实现AQS的模板方法来实现其内部同步逻辑的。

  1. 同步状态:AQS使用一个volatile int类型的变量来表示同步状态,通过内置的FIFO(先进先出)队列(也称为CLH队列,一个虚拟的双向队列)来完成获取资源线程的排队工作。这个状态变量是线程共享的,用于表示同步资源的状态。
  2. 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的行为

  1. 尝试获取锁:线程A首先调用lock()方法,该方法内部会尝试通过compareAndSetState(0, 1)将锁的状态从0(未锁定)更改为1(锁定)。如果当前没有其他线程持有锁(即锁状态为0),则线程A成功获取锁。
  2. 执行业务逻辑:线程A在获取锁之后执行其业务逻辑。

线程B和C的行为(几乎同时)

当线程A持有锁时,线程B和C尝试获取锁。

  1. 调用acquire(1):线程B和C都调用acquire(1)方法,该方法是非公平锁获取锁的主要入口。
  2. 尝试非公平获取锁:acquire(1)内部调用tryAcquire(1),进而调用nonfairTryAcquire(1)。nonfairTryAcquire(1)首先检查当前锁状态是否为0(即未锁定),如果是,则尝试通过compareAndSetState(0, 1)获取锁。但由于线程A已经持有锁,所以B和C的这一步都会失败。(如果占用线程和当前线性为同一线程时,即为可重入锁
  3. 添加等待者:由于nonfairTryAcquire(1)返回false,线程B和C都会调用addWaiter()方法将自己封装成一个节点(Node),并通过enq(node)方法将节点加入到等待队列中。如果队列为空(即还没有其他线程在等待),则初始化头节点(head)并设置尾节点(tail)为新加入的节点。否则,将新节点添加到队尾。
  4. 进入等待队列并等待:线程B和C在加入等待队列后,会调用acquireQueued(node, 1)方法。在这个方法中,线程会进入一个自旋循环,不断检查前驱节点的状态,并尝试通过park()方法使自己进入等待状态(阻塞)。如果前驱节点的状态是SIGNAL(-1),则线程会通过LockSupport.park(this)被阻塞,直到被唤醒。

线程A释放锁

  1. 释放锁:当线程A完成其业务逻辑后,会调用unlock()方法来释放锁。这会将锁的状态从1改回0,并唤醒等待队列中的一个线程(如果有的话)。
  2. 唤醒等待线程:在释放锁的过程中,unlock()方法会调用LockSupport.unpark(thread)来唤醒等待队列中的一个线程。由于是非公平锁,被唤醒的线程不一定是等待时间最长的线程(即队列的头部线程)。

线程B或C被唤醒

被唤醒的线程(可能是B也可能是C,这取决于线程调度器的决策)会重新进入acquireQueued(node, 1)方法的自旋循环,并再次尝试获取锁。如果此时锁已被释放(即状态为0),则该线程可能会成功获取锁并退出自旋循环,继续执行其业务逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1897352.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【网络安全】Host碰撞漏洞原理+工具+脚本

文章目录 漏洞原理虚拟主机配置Host头部字段Host碰撞漏洞漏洞场景工具漏洞原理 Host 碰撞漏洞,也称为主机名冲突漏洞,是一种网络攻击手段。常见危害有:绕过访问控制,通过公网访问一些未经授权的资源等。 虚拟主机配置 在Web服务器(如Nginx或Apache)上,多个网站可以共…

YOLOv8改进 添加CVPR2024 PKINet中注意力机制CAAttention

一、PKINet论文 论文地址:2403.06258 (arxiv.org) 二、CAAttention结构 CAA(Context Anchor Attention)注意力模块是一种用于捕捉长距离上下文信息的并行模块。 在计算机视觉领域中,上下文信息是指与目标物体或任务相关的周围环境和语境信息。上下文信息可以帮助我们更好…

【UE5.1 角色练习】13-枪械射击——拿出与收起武器

目录 效果 步骤 一、安装射击武器 二、拿武器和收武器 效果 步骤 一、安装射击武器 1. 在虚幻商城中将“FPS Weapon Bundle”添加到工程中,由于我们使用的是5.1版本,我们可以先将该资产放入UE4工程中,然后迁移到5.1版本的工程 2. 打开角…

threejs基础入门案例研究——三维立体物体沿指定曲线逐渐增长变长

效果 threejs按照指定曲线效果逐渐增长 全部代码 主要思路是先创建指定曲线路径,并将其分为1000个点,然后按照自定义路线拉伸三维物体,从头遍历点的位置,然后放入物体拉伸路径中,实现缓慢增长效果 全部代码如下: <template><div class="threejs">…

工作助手VB开发笔记(2)

今天继续讲功能 2.功能 2.9开机自启 设置程序随windows系统启动&#xff0c;其实就是就是将程序加载到注册表 Public Sub StartRunRegHKLM()REM HKEY_LOCAL_MACHINE \ SOFTWARE \ WOW6432Node \ Microsoft \ Windows \ CurrentVersion \ RunDim strName As String Applicat…

高效任务分配的常见7步法

高效的任务分配有助于优化资源配置&#xff0c;提升开发效率与质量&#xff0c;降低成本和项目风险&#xff0c;最终提高客户满意度。如果任务分配不合理&#xff0c;可能导致资源浪费&#xff0c;造成项目延期和成本超支&#xff0c;影响工作质量&#xff0c;增加项目风险。 因…

内核错误定位

内核打印出如下&#xff1a; 在代码目录输入&#xff1a; ./prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gdb kernel/vmlinux 进入gdb 命令模式 输入 l *(rk628_csi_probe0xf0) 能定位到出现问题地方。 最后就…

Netty学习(Netty入门)

概述 Netty是什么 Netty的地位 Netty的优势 HelloWorld public class HelloClient {public static void main(String[] args) throws InterruptedException {// 1. 启动类new Bootstrap()// 2. 添加 EventLoop.group(new NioEventLoopGroup())// 3. 选择客户端 channel 实现.…

lua入门(1) - 基本语法

本文参考自&#xff1a; Lua 基本语法 | 菜鸟教程 (runoob.com) 需要更加详细了解的还请参看lua 上方链接 交互式编程 Lua 提供了交互式编程模式。我们可以在命令行中输入程序并立即查看效果。 Lua 交互式编程模式可以通过命令 lua -i 或 lua 来启用&#xff1a; 如下图: 按…

【车载开发系列】J-Link/JFlash 简介与驱动安装方法

【车载开发系列】J-Link/JFlash 简介与驱动安装方法 【车载开发系列】J-Link/JFlash 简介与驱动安装方法 【车载开发系列】J-Link/JFlash 简介与驱动安装方法一. 软件介绍二. 下载安装包二. 开始安装三. 确认安装四. J-Flash的使用 一. 软件介绍 J-Link是SEGGER公司为支持仿真…

springboot校园安全通事件报告小程序-计算机毕业设计源码02445

Springboot 校园安全通事件报告小程序系统 摘 要 随着中国经济的飞速增长&#xff0c;消费者的智能化水平不断提高&#xff0c;许多智能手机和相关的软件正在得到更多的关注和支持。其中&#xff0c;校园安全通事件报告小程序系统更是深得消费者的喜爱&#xff0c;它的出现极大…

Debug-017-elementUI-el-cascader组件首次选择选项不触发表单的自定义校验

前情提要&#xff1a; 今天维护一个表单校验的时候发现一件事情&#xff0c;就是在表单中使用了 el-cascader组件&#xff0c;希望根据接口返回数据去动态校验一下这里面的选项&#xff0c;符合逻辑就通过自定义的表单校验&#xff0c;不符合就在这一项的下面标红提示。做的时候…

Mean teacher are better role models-论文笔记

论文笔记 资料 1.代码地址 2.论文地址 https://arxiv.org/pdf/1703.01780 3.数据集地址 CIFAR-10 https://www.cs.utoronto.ca/~kriz/cifar.html 论文摘要的翻译 最近提出的Temporal Ensembling方法在几个半监督学习基准中取得了最先进的结果。它维护每个训练样本的标签…

C语言图书馆管理系统(管理员版)

案例&#xff1a;图书馆管理系统&#xff08;管理员版&#xff09; 背景&#xff1a; 随着信息技术的发展和普及&#xff0c;传统的图书馆管理方式已经无法满足现代图书馆高效、便捷、智能化的管理需求。传统的手工登记、纸质档案管理不仅耗时耗力&#xff0c;而且容易出现错…

RT-Thread Studio与CubeMX联合编程之rtthread启动

看到了好多文章&#xff0c;在rtthread studio中启用mx&#xff0c;后总是复制mx相关msp函数到rt的board.c文件下&#xff0c;实际使用过程中发现并不需要&#xff0c;这里我们看下rt启动流程&#xff0c;看下到底需要不。 1.打开startup_stm32h743xx.S文件&#xff0c;看下芯片…

区块链技术如何改变供应链管理?

引言 供应链管理在现代商业中扮演着至关重要的角色&#xff0c;确保产品和服务从原材料到最终消费者的顺利流转。然而&#xff0c;当前的供应链管理面临诸多挑战&#xff0c;如信息不透明、数据篡改和效率低下等问题&#xff0c;这些问题严重制约了供应链的整体效能和可信度&am…

用kimi和claude自动生成时间轴图表

做时间轴图表并不难&#xff0c;但是很麻烦&#xff0c;先要大量收集相关事件&#xff0c;然后在一些图表软件中反复调整操作。现在借助AI工具&#xff0c;可以自动生成了。 首先&#xff0c;在kimi中输入提示词来获取某个企业的大事记&#xff1a; 联网检索&#xff0c;元语…

【专业指南】移动硬盘坏道下的数据恢复之道

移动硬盘坏道揭秘&#xff1a;数据安全的隐形挑战 在数据日益成为核心资产的今天&#xff0c;移动硬盘作为便携存储的代名词&#xff0c;承载着无数用户的重要信息。然而&#xff0c;随着使用时间的增长和不当操作的影响&#xff0c;移动硬盘可能会遭遇“坏道”这一棘手问题。…

14-30 剑和诗人4 – 具有长上下文窗口的微调 LLM 的数据设计

LLM 中的长上下文窗口的挑战 微调大型语言模型 (LLM) 面临的最大挑战之一在于处理较长的上下文窗口。LLM 经过大量文本数据训练&#xff0c;能够理解和生成类似人类的语言。然而&#xff0c;在推理过程中&#xff0c;这些模型的上下文窗口有限&#xff0c;通常约为 2,048 个标…

基于MCU平台的HMI开发的性能优化与实战(下)

继上篇《基于MCU平台的HMI开发的性能优化与实战&#xff08;上&#xff09;》深入探讨了提升MCU平台HMI开发效率和应用性能的策略后&#xff0c;本文将专注于NXP i.MX RT1170 MCU平台的仪表盘开发实践。我们将重点介绍Qt for MCUs的优化技巧&#xff0c;展示如何通过实际案例应…