当前位置: 首页 > news >正文

Java并发编程学习笔记:AQS

Java并发编程学习笔记:AQS

  • 一、底层原理
    • 核心功能
      • 同步状态管理
      • CLH 队列和线程调度机制
      • 独占模式与共享模式
      • 模板方法设计模式
      • 自旋、阻塞与超时机制
    • 运行流程
  • 二、锁的公平性
    • 公平锁
    • 非公平锁
  • 三、容器实现

JUC中的AQS(AbstractQueuedSynchronizer)本质上是一个用于构建线程同步器的框架(抽象队列式同步器),它实现了Java中锁和同步器的底层机制。

一、底层原理

核心功能

同步状态管理

  • AQS 使用一个受保护的 volatile 类型变量 state 来表示同步状态。 volatile 保证了对 state 变量的读写操作具有原子性和可见性,使得多线程环境下,各线程可以正确地感知到同步状态的变化。

  • AQS 提供基于 CAS原子指令的操作方法来实现无锁化的状态更新 ,避免了使用传统锁带来的性能开销。

CLH 队列和线程调度机制

  • AQS 内部维护了一个FIFO的双向队列,每个节点(Node)代表一个尝试获取同步状态但未成功的线程。 这个队列来源于 CLH 锁,通过链表结构和wait-status字段实现线程间的阻塞与唤醒。

  • 当线程无法立即获取到同步状态时,会被构造为一个新的 Node 并加入等待队列尾部; 而当同步状态释放时,根据锁的公平性寻找可被唤醒的线程并将其激活。这一过程涉及挂起线程和恢复线程的执行的方法。

独占模式与共享模式

  • 独占模式: 仅允许一个线程持有同步状态。同一时间只有一个线程能够获取到锁,并且支持重入,即同一个线程可以多次获取而不受限制。

  • 共享模式: 允许多个线程同时持有同步状态,但可能需要遵循某种条件或限制数量,让多个线程可以共享这些资源,直至资源耗尽。

模板方法设计模式

AQS 利用模板方法设计模式,提供了基本的框架和关键算法,子类只需重写几个核心方法即可定制自己的同步器行为。

  • tryAcquire(int arg): 尝试获取同步状态,由子类根据其具体逻辑实现。

  • tryRelease(int arg): 尝试释放同步状态,同样需要自行定义逻辑。

  • 对于共享模式还有相应的获取与释放方法。

自旋、阻塞与超时机制

  • AQS 支持自旋等待,在尝试获取同步状态失败后,线程会在一段短暂的时间内循环检查同步状态是否满足获取条件,而不是立即进入阻塞队列。

  • AQS 支持设置获取同步状态时的超时机制,提供限时等待的功能。

运行流程

下面是一个模拟银行账户取款流程中所涉及到AQS的具体实现。

同步状态管理: 在这个场景中,维护一个volatile变量作为同步状态可以简单理解为“是否持有锁”,初始值通常为0,表示未锁定。当线程尝试获取锁(即取款操作开始前)时,调用tryAcquire()方法,该方法使用CAS原子操作尝试将同步状态从0改为1,如果成功则说明获取到锁。

线程排队与阻塞机制:

  1. 如果多个线程同时请求取款,当第一个线程获取到锁后,其他线程会发现同步状态已非0,它们在tryAcquire()中失败。

  2. 失败的线程会被封装成一个节点(Node),并加入到AQS内部的CLH双向队列尾部。 每个节点代表一个等待获取锁的线程,并且具有指向前后节点的引用,形成FIFO队列结构。

  3. 加入队列后的线程通过方法进入阻塞状态,释放CPU资源。

锁的公平性保证: 可以根据需要实现公平锁或非公平锁。 公平锁遵循先来后到的原则,每次释放锁时都会唤醒等待队列中的第一个线程;而非公平锁则可能直接尝试获取锁,即使有其他线程已经在等待。

锁的释放与唤醒机制: 当持有锁的线程完成取款操作后,它会在finally块中调用release()方法释放锁。release()方法会执行tryRelease()逻辑,将同步状态设置回0,表示锁被释放。 之后AQS会检查等待队列找到合适的线程,并唤醒该线程,使其能够重新竞争锁并执行取款操作。

在实际应用中,用户线程并不是无限期地等待,而是设定一个合理的时间限制。通过AQS所支持的获取锁时设置超时时间或者对线程进行中断处理进行设置限制。

二、锁的公平性

在AQS中,公平性和非公平性锁的实现主要体现在获取锁的策略上。

一般情况下,公平锁可以减少线程饥饿的可能性,但可能会降低系统的整体吞吐量;非公平锁虽然可能导致线程饥饿,但在许多场景下可以获得更好的并发性能。

公平锁

公平锁保证了线程请求锁的顺序与它们进入同步队列的顺序一致。在AQS中,公平锁的实现通常会在tryAcquire()方法中检查等待队列是否有其他线程正在排队等待。如果有,则当前线程不会尝试获取锁,而是直接返回失败;只有当等待队列为空时,才会尝试获取锁并修改同步状态。

hasQueuedPredecessors()用于检查是否存在已经在等待队列中的前驱节点,即是否有其他线程在等待。

protected boolean tryAcquire(int arg) {if (hasQueuedPredecessors() || !compareAndSetState(0, 1)) {return false;}setExclusiveOwnerThread(Thread.currentThread());return true;
}

非公平锁

非公平锁则不考虑线程等待的先后顺序,在有机会获取锁的时候就会立即尝试获取。

在下面实现中只要同步状态为0且能够成功通过CAS设置为1,那么线程就可以获取到锁,而不管等待队列的状态如何。

protected boolean tryAcquire(int arg) {if (getState() == 0 && compareAndSetState(0, 1)) {setExclusiveOwnerThread(Thread.currentThread());return true;}return false;
}

三、容器实现

ReentrantLock(可重入锁): ReentrantLock 是一个可重入锁,提供了公平锁和非公平锁两种模式。通过继承自AQS并实现其模板方法,它能够支持锁的获取、释放以及线程阻塞与唤醒等功能。

Semaphore(信号量): Semaphore 用于控制同时访问特定资源的线程数量。在AQS基础上,Semaphore管理着一组许可证,每个acquire()操作都会尝试减少许可证数量,若不足则阻塞线程;每个release()操作则会增加许可证数量并可能唤醒等待的线程。

CountDownLatch(闭锁): CountDownLatch 允许一个或多个线程等待其他线程完成一组操作后再继续执行。它有一个计数器,通过countDown()方法递减,当计数器达到0时,所有因调用await()而被阻塞的线程都将被唤醒继续执行。AQS在这里负责管理阻塞的线程,并在计数器变化时调整线程状态。

CyclicBarrier(循环屏障): CyclicBarrier 可以让一组线程在某个屏障点上互相等待,直到所有线程都到达这个点后才能继续执行。当最后一个线程调用await()时,所有在此之前的等待线程将被唤醒。AQS负责管理等待线程队列,并在条件满足时释放所有等待线程。

ReadWriteLock(读写锁): ReentrantReadWriteLock是一个实现了读写分离锁的接口,内部包含两个锁:读锁和写锁。读锁可以被多个线程同时持有,而写锁在同一时间内只能被一个线程持有,这样既保证了数据一致性又提高了读取操作的并发性能。

相关文章:

Java并发编程学习笔记:AQS

Java并发编程学习笔记:AQS 一、底层原理核心功能同步状态管理CLH 队列和线程调度机制独占模式与共享模式模板方法设计模式自旋、阻塞与超时机制 运行流程 二、锁的公平性公平锁非公平锁 三、容器实现 JUC中的AQS(AbstractQueuedSynchronizer)…...

Github上哪些好用的工具

专注于web漏洞挖掘、内网渗透、免杀和代码审计,感谢各位师傅的关注!网安之路漫长,与君共勉! Qexo-爱写博客的师傅强烈推荐 漂亮的 Hexo 静态博客编辑器。该项目是基于 Django 的 Hexo 静态博客管理后台,支持文章管理、…...

如何确保面试流程标准化操作,避免人为因素影响**

一、背景 在招聘过程中,面试作为关键环节,其标准化操作至关重要。标准化不仅有助于提高面试效率和质量,还能减少人为因素的影响,确保公平、公正和客观。本文将从以下八个方面探讨如何确保面试流程的标准化操作。 二、明确面试标准 制定明确的面试标准和要求,确保所有面试…...

YOLOv7改进 | 更换主干网络之PP-LCNet

前言:Hello大家好,我是小哥谈。PP-LCNet是一个由百度团队针对Intel-CPU端加速而设计的轻量高性能网络。它是一种基于MKLDNN加速策略的轻量级卷积神经网络,适用于多任务,并具有提高模型准确率的方法。与之前预测速度相近的模型相比,PP-LCNet具有更高的准确性。此外,对于计…...

MySQL基础-----多表查询之子查询

目录 前言 子查询概述 1.概念 2.分类 一、标量子查询 二、列子查询 三、行子查询 四、表子查询 前言 上一期我们讲了内外连接查询以及自连接查询,那么本期我们就学习多表查询的子查询。本期会详细讲解什么是子查询,以及子查询的相关功能&#xf…...

nginx应用场景(附配置)

场景1:web服务器 server {listen 80;server_name example.com; # 替换为您的域名location / {root /data/wwwroot;index index.html index.htm;} }server {listen 443 ssl;server_name example.com; # 替换为您的域名ssl_certificate /path/to/certificate.crt;ssl…...

tvm android_rpc_test.py执行报错解决

执行 python3 tests/android_rpc_test.py 报错&#xff1a; Run CPU test ... Traceback (most recent call last): File "tests/android_rpc_test.py", line 129, in <module> test_rpc_module() File "tests/android_rpc_test.py", line …...

十、项目沟通管理

十、项目沟通管理 从马斯洛需求的各个层级上&#xff0c;都需要沟通的介入。如果缺乏沟通&#xff0c;甚至可能严重损伤身心健康。 沟通渠道 1、 规划沟通管理 ​ 规划沟通管理是基于每个相关方或相关方群体的信息需求、可用的组织资产&#xff0c;以及具体项目的需求&#x…...

SQL设计时增加说明列

后关闭sql Studio,然后打开注册表,注册表地址: 计算机\HKEY_CURRENT_USER\SOFTWARE\Microsoft\SQL Server Management Studio\18.0_IsoShell\DataProject 如有版本不同,红色内容有所变化,修改内容如下: SSVPropViewColumnsSQL70,SSVPropViewColumnsSQL80 全修改为 1,2,6,7…...

前端提高性能——使用Intersection Observer API对图片视频进行懒加载

前言 最近做了一个项目是类似于商城的&#xff0c;需要放很多图片&#xff0c;在用户选择一页五十条时&#xff0c;页面加载速度会比较慢。为了提高性能&#xff0c;选择用Intersection Observer API 实现图片懒加载。 实现步骤 一、html代码&#xff1a; <img class&qu…...

杂七杂八111

MQ 用处 一、异步。可提高性能和吞吐量 二、解耦 三、削峰 四、可靠。常用消息队列可以保证消息不丢失、不重复消费、消息顺序、消息幂等 选型 一Kafak:吞吐量最大&#xff0c;性能最好&#xff0c;集群高可用。缺点&#xff1a;会丢数据&#xff0c;功能较单一。 二Ra…...

微信小程序(一)

WebView app.是全局配置&#xff0c;app.json是全局配置文件&#xff0c;在页面的.json配置文件中的配置会覆盖我们全局的配置 快捷键&#xff1a; .box 敲回车 ----- <view class"box"></view> .row*8 敲回车&#xff1a; .row{$}*8 敲回车 案例1&…...

【DL经典回顾】激活函数大汇总(十二)(GLU ReGLU附代码和详细公式)

激活函数大汇总&#xff08;十二&#xff09;&#xff08;GLU & ReGLU附代码和详细公式&#xff09; 更多激活函数见激活函数大汇总列表 一、引言 欢迎来到我们深入探索神经网络核心组成部分——激活函数的系列博客。在人工智能的世界里&#xff0c;激活函数扮演着不可或…...

【C++】string类初步介绍

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. 为什么学习string类1.1 C语言中的字符串1.2 推荐学习网站 2. 标准库中的string类2.1 string类2.2 string类的常用接口说明2.2.1 constructor2.2.2 遍历string2.2.2.1 下标加[]遍历2.2.2.2 迭代器&#xff08;itera…...

HCIP --- BGP 综合实验

目录 实验拓扑图&#xff1a; 实验要求&#xff1a; 实验步骤&#xff1a; 1.划分IP地址 R1的配置 R2的配置 R3的配置 R4的配置 R5的配置 R6的配置 R7的配置 R8的配置 2.检测查询IP地址 3.OSPF 建邻 4.查询OSPF 建邻是否成功 5.AS 2 内部BGP 建邻 a. AS 2 内部 IBG…...

【优选算法】专题1 -- 双指针 -- 移动零

前言: &#x1f4da;为了提高算法思维&#xff0c;我会时常更新这个优选算法的系列&#xff0c;这个专题是关于双指针的练习 &#x1f3af;个人主页&#xff1a;Dream_Chaser&#xff5e;-CSDN博客 一.移动零&#xff08;easy&#xff09; 描述&#xff1a; 「数组分两块」是⾮…...

【计算机视觉】二、图像形成:2、几何基元和几何变换:2D变换

文章目录 一、向量和矩阵的基本运算二、几何基元和变换1、几何基元(Geometric Primitives)2、几何变换(Geometric Transformations)1. 各种变换的关系2. 变换公式3. 2D变换的层次4. python实现 一、向量和矩阵的基本运算 【计算机视觉】二、图像形成&#xff1a;1、向量和矩阵…...

蓝桥杯---棋盘(典型的二维差分问题)

题目链接&#xff1a;棋盘 这道题真的是非常典型的二维差分问题了&#xff08;在我个人看来&#xff09;&#xff0c;题目中的0和1&#xff0c;我们直接让差分数组&#xff0c;偶数就是0&#xff0c;奇数就是1.初始化是0&#xff0c;是白子&#xff08;偶数&#xff09;&#x…...

OpenHarmony教程指南—ArkTS时钟

简单时钟 介绍 本示例通过使用ohos.display 接口以及Canvas组件来实现一个简单的时钟应用。 效果预览 使用说明 1.界面通过setInterval实现周期性实时刷新时间&#xff0c;使用Canvas绘制时钟&#xff0c;指针旋转角度通过计算得出。 例如&#xff1a;"2 * Math.PI /…...

uniapp遇到的问题

【uniapp】小程序中input输入框的placeholder-class不生效解决办法 解决&#xff1a;写在scope外面 uniapp设置底部导航 引用&#xff1a;https://www.jianshu.com/p/738dd51a0162 【微信小程序】moveable-view / moveable-area的使用 https://blog.csdn.net/qq_36901092/…...

食品批发厂家口碑推荐榜

在食品批发行业&#xff0c;选择一家口碑良好的厂家至关重要。优质的食品批发厂家不仅能提供高品质的产品&#xff0c;还能保障稳定的供应和良好的售后服务。今天&#xff0c;我们就来为大家推荐一些口碑出众的食品批发厂家&#xff0c;其中惠州市佳德旺食品有限公司表现尤为突…...

基于Simulink的自抗扰控制(ADRC)在OBC前级的应用

手把手教你学Simulink——基于Simulink的自抗扰控制(ADRC)在OBC前级的应用​ (附:OBC前级拓扑剖析+ADRC抗扰原理+TD/ESO/NLSEF算法推导+Simulink全模型搭建+动态响应/谐波抑制对比+实机部署指南) 摘要​ 车载充电机(OBC)前级作为交流-直流(AC-DC)整流核心,需将电网…...

手把手教你用llama.cpp的RPC功能,把旧笔记本变成大模型推理服务器(附性能对比)

用llama.cpp的RPC功能将旧笔记本改造成大模型推理服务器的完整指南 1. 为什么需要分布式推理环境&#xff1f; 当我在2023年第一次尝试在个人笔记本上运行7B参数的大语言模型时&#xff0c;即使经过量化处理&#xff0c;生成每个token仍需要近10秒——这种体验简直令人崩溃。但…...

终极指南:一键解决iPhone USB网络共享驱动问题

终极指南&#xff1a;一键解决iPhone USB网络共享驱动问题 【免费下载链接】Apple-Mobile-Drivers-Installer Powershell script to easily install Apple USB and Mobile Device Ethernet (USB Tethering) drivers on Windows! 项目地址: https://gitcode.com/gh_mirrors/ap…...

MGeo地址实体对齐镜像快速上手:5分钟部署,支持自定义阈值

MGeo地址实体对齐镜像快速上手&#xff1a;5分钟部署&#xff0c;支持自定义阈值 1. 引言&#xff1a;地址数据混乱&#xff0c;是时候换个思路了 你有没有被这样的问题困扰过&#xff1f; 公司CRM系统里&#xff0c;同一个客户因为地址写法不同&#xff0c;被重复记录了十几…...

千问3.5-2B在VSCode中的集成应用:基于CodeX的智能编程助手搭建

千问3.5-2B在VSCode中的集成应用&#xff1a;基于CodeX的智能编程助手搭建 1. 引言 作为一名开发者&#xff0c;你是否经常在编码过程中遇到这些问题&#xff1a;记不清某个API的具体用法&#xff1f;需要快速生成重复性代码片段&#xff1f;遇到报错信息却找不到清晰的解释&…...

飞书机器人告警配置避坑指南:夜莺监控常见报错解决方案

飞书机器人告警配置避坑指南&#xff1a;夜莺监控常见报错解决方案 深夜的告警风暴里&#xff0c;飞书机器人突然罢工是什么体验&#xff1f;上周三凌晨2点&#xff0c;当我面对满屏的Key Words Not Found和sign match fail报错时&#xff0c;终于理解了为什么运维工程师的咖啡…...

Proteus仿真实战:基于STM32的智能环境感知与联动控制系统(附源码)

1. 项目背景与核心功能 想象一下这样的场景&#xff1a;当你走进书房时&#xff0c;灯光自动亮起&#xff1b;当室内温度过高时&#xff0c;空调自动开启&#xff1b;当光线不足时&#xff0c;窗帘缓缓拉开。这些看似科幻的场景&#xff0c;其实用STM32单片机和Proteus仿真就能…...

ModelScope环境安装避坑指南:从NLP到语音,不同领域模型依赖到底怎么装?

ModelScope环境安装避坑指南&#xff1a;从NLP到语音&#xff0c;不同领域模型依赖到底怎么装&#xff1f; 当你第一次尝试在ModelScope上运行一个语音识别模型时&#xff0c;系统突然报错提示缺少libsndfile库&#xff1b;当你满怀期待地安装CV模型时&#xff0c;却因为mmcv版…...

Ryzen SDT调试工具:解锁AMD处理器潜能的系统级配置平台

Ryzen SDT调试工具&#xff1a;解锁AMD处理器潜能的系统级配置平台 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://g…...