AbstractQueuedSynchronizer

news2024/11/26 19:37:23

目录

    • AQS是什么
    • AQS什么样
      • 内部类
      • 成员变量
      • 方法public
      • 如果不使用AQS会怎样
    • AQS的应用
      • ReentrantLock
        • Sync
        • NonfairSync
        • FairSync
      • 其他实现

AQS是什么

AbstractQueuedSynchronizer(AQS)是Java中的一个并发工具,位于java.util.concurrent.locks包中,用于实现基于锁的同步机制。它是许多同步类(如ReentrantLockSemaphore等)的基础,并提供了一种用于实现独占锁(exclusive locks)和共享锁(shared locks)等同步机制的框架。

AQS是一个抽象类,它通过维护一个等待队列来管理线程的同步状态。它的主要设计思想是,当某个线程尝试获取锁时,如果锁不可用,该线程会被放入等待队列,然后被阻塞。当锁释放时,AQS会从等待队列中唤醒适当的线程,使其能够竞争锁。

AQS什么样

内部类

类名作用
NodeNode类表示等待队列中的一个节点,用于构建等待队列、实现线程的阻塞与唤醒,以及表示等待线程。
ExclusiveNodeExclusiveNodeNode类的子类,表示独占模式(exclusive mode)下的节点,用于独占锁的等待队列。
SharedNodeSharedNodeNode类的子类,表示共享模式(shared mode)下的节点,用于共享锁的等待队列。
ConditionNodeConditionNodeNode类的子类,表示条件等待队列中的节点,用于支持条件变量的等待和唤醒机制。
ConditionObjectConditionObjectAbstractQueuedSynchronizer的内部类,用于实现条件变量,允许线程等待特定条件。

这些内部类在AbstractQueuedSynchronizer的实现中扮演着不同的角色,从构建等待队列、表示等待线程、实现条件等待机制,到支持不同模式的锁等待。通过这些内部类的使用,AQS能够支持各种同步场景和锁的实现,从而实现多线程的协调和同步。

成员变量

先看看AQS里都有哪些成员变量:
当然,我可以为您解释这些成员变量的作用。以下是您列出的成员变量的简要解释和作用的表格展示:

变量名变量类型变量作用
WAITINGint表示线程处于等待状态,即等待获取锁。
CANCELLEDint表示线程在等待队列中等待时被取消,即等待被中断或其他原因取消。
CONDNode一个特殊的标识,用于表示等待队列中的节点是一个条件等待节点而不是独占或共享模式的节点。
headNode等待队列中的头节点,即队列中等待时间最长的节点。
tailNode等待队列中的尾节点,即队列中等待时间最短的节点。
stateint表示同步状态的变量,可以是任意整数值,根据具体实现的需要来表示不同的状态。
UUnsafe提供了一些底层的操作,允许直接对内存进行操作,用于实现一些底层同步原语。
STATElong一个偏移量,用于表示在AbstractQueuedSynchronizer类中用于操作state变量的偏移量。
HEADlong一个偏移量,用于表示在AbstractQueuedSynchronizer类中用于操作head变量的偏移量。
TAILlong一个偏移量,用于表示在AbstractQueuedSynchronizer类中用于操作tail变量的偏移量。

这些成员变量在AbstractQueuedSynchronizer中用于维护等待队列、线程状态和同步状态等信息,从而实现了基于队列的线程同步和协调机制。不同的变量在整个机制中扮演着不同的角色,以实现正确的多线程同步行为。

方法public

我们来看一下AQS都提供了哪些方法

方法名参数含义方法作用
acquireint arg:请求获取锁的参数尝试获取锁,如果获取不到则将调用线程置于阻塞状态,直到锁可用或线程被中断。
acquireInterruptiblyint arg:请求获取锁的参数类似于acquire,但是允许线程在等待锁的过程中被中断。如果线程在等待时被中断,会抛出InterruptedException异常。
tryAcquireNanosint arg:请求获取锁的参数,long nanosTimeout:等待时间尝试获取锁,但最多等待指定的时间。如果在超时前未能获取锁,则返回结果指示是否成功获取。
releaseint arg:释放锁的参数释放锁,通常在获取锁成功后调用。释放锁会唤醒等待队列中的其他线程,使其有机会竞争锁。
acquireSharedint arg:请求获取共享锁的参数类似于acquire,但是用于共享锁的获取。多个线程可以同时获取共享锁,而不像独占锁一样只能有一个线程持有。
acquireSharedInterruptiblyint arg:请求获取共享锁的参数类似于acquireShared,但是允许线程在等待共享锁的过程中被中断。如果线程在等待时被中断,会抛出InterruptedException异常。
tryAcquireSharedNanosint arg:请求获取共享锁的参数,long nanosTimeout:等待时间类似于tryAcquireNanos,但是用于共享锁的获取。
releaseSharedint arg:释放共享锁的参数释放共享锁,通常在获取共享锁成功后调用。释放共享锁会唤醒等待队列中的其他线程,使其有机会竞争锁。
hasQueuedThreads-判断是否有线程在等待队列中等待获取锁。
hasContended-判断是否有线程在竞争锁。
getFirstQueuedThread-获取等待队列中的第一个线程,但不移除。
isQueuedThread thread:要检查的线程判断指定线程是否在等待队列中等待获取锁。
apparentlyFirstQueuedIsExclusive-判断等待队列中的第一个线程是否为独占模式(exclusive mode)线程。
hasQueuedPredecessors-判断调用线程是否有在等待队列中的前驱线程。如果有前驱线程,则可能需要执行阻塞操作。
getQueueLength-获取等待队列中的线程数。
getQueuedThreads-获取在等待队列中等待获取锁的所有线程。
getExclusiveQueuedThreads-获取在等待队列中等待获取独占锁的所有线程。
getSharedQueuedThreads-获取在等待队列中等待获取共享锁的所有线程。
toString-返回对象的字符串表示,通常包括等待队列中的线程信息。
ownsThread thread:要检查的线程判断指定线程是否是当前持有锁的线程。
hasWaiters-判断是否有线程在等待队列中等待释放锁。
getWaitQueueLength-获取等待队列中等待释放锁的线程数。
getWaitingThreadsCondition condition:相关的条件获取与指定条件相关的等待线程列表。

这些方法是AbstractQueuedSynchronizer类的核心方法,用于实现多线程同步和协调。

如果不使用AQS会怎样

AQS的应用

我们来直接举个例子

ReentrantLock

ReentrantLock中有3个内部类
在这里插入图片描述

Sync

AQS的子类,其实基本上实现了ReentrentLock的大部分方法,ReentrentLock开放出来的大部分方法其实都是直接调用的Sync里的方法

方法名参数含义方法作用
tryLocklong timeout, TimeUnit unit尝试获取锁,如果锁没有被其他线程持有,则获取锁并返回true,如果在指定的时间内无法获取锁,则返回false。
initialTryLock-作为tryLock的一种形式,是在ReentrantLock的构造函数中使用的,用于初始化锁。
lock-获取锁,如果锁已经被其他线程持有,则当前线程会被阻塞,直到获取到锁。
lockInterruptibly-获取锁,如果锁已经被其他线程持有,允许线程在等待时被中断。如果线程在等待时被中断,会抛出InterruptedException异常。
tryLockNanoslong timeout尝试在指定的时间内获取锁,如果锁没有被其他线程持有,则获取锁并返回true。如果在指定的时间内无法获取锁,则返回false。
tryRelease-尝试释放锁。
isHeldExclusively-判断当前线程是否持有独占锁。
newCondition-创建一个新的Condition对象,用于支持条件等待。
getOwner-获取当前持有独占锁的线程,如果没有线程持有锁,返回null。
getHoldCount-获取当前线程持有锁的次数,用于可重入锁的计数。
isLocked-判断锁是否被任何线程持有。

NonfairSync

Sync的子类,非公平锁的实现。

方法名参数作用
initialTryLockunused尝试获取锁,如果获取成功返回true,失败返回false。该方法只在构造方法中调用一次。
tryAcquireacquires独占式尝试获取同步状态。如果获取成功返回true,否则返回false。

FairSync

Sync的子类,公平锁的实现

方法名参数作用
initialTryLockunused尝试获取锁,当等待队列无线程等待并且state为0。不同于NonfairSync,公平锁只有无竞争时才会尝试获取锁。
tryAcquireacquires尝试获取同步状态,如果队列中第一个节点是当前线程就获取成功,不是则失败。

FairSync也继承自AQS,但实现了公平的锁获取语义 - 等待时间最长的线程最先获得锁。

这两个类开始起作用是在创建ReentrentLock的时候,这里
在这里插入图片描述

其他实现

  • CountDownLatch: 用来进行线程之间同步协作,可以实现一个线程等待其他线程完成某件事情之后再执行。
  • CyclicBarrier: 用来进行线程之间同步协作,可以实现让一组线程达到一个屏障时被阻塞,直到最后一个线程到达屏障时屏障才会开门,所有被屏障拦截的线程才会继续执行。
  • Semaphore: 用于控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。
  • Exchanger: 用于进行线程间的数据交换。它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。
  • BlockingQueue: 一个支持两个附加操作的队列。在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。
  • ForkJoinPool: Fork/Join框架中的线程池实现类,用于异步执行fork/join任务。

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

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

相关文章

最新Ubuntu LVGL SDL模拟器安装

前言 本文主要说明Ubuntu 23.4安装LVGL 9.0以及基于SDL的模拟环境。 代码下载 访问lv_port_pc_eclipse可以看到相信信息,官方已经打包好了整个代码环境。 安装CMAKE。 sudo apt install cmake安装SDL。 sudo apt-get update && sudo apt-get install …

HTML(JavaEE初级系列12)

目录 前言: 1.HTML结构 1.1认识HTML标签 1.2HTML文件基本结构 1.3标签层次结构 1.4快速生成代码框架 2.HTML常见标签 2.1注释标签 2.2标题标签:h1-h6 2.3段落标签:p 2.4换行标签: br 2.5格式化标签 2.6图片标签&#…

新手家长必读:英国ISEB考试局CEO为低龄留学家庭深度解析ISEB

大家都知道,英国私校备考难就难在流程繁琐,菁英私校笔面试风格各异,考试时间各不相同。但在进入私校笔面试之前,还有非常重要的一步——通过ISEB pre-test考试。      作为英校申请敲门砖,学生在注册之后&#xff…

STM32 F103C8T6学习笔记7:双机无线串口通信

今日尝试配通俩个C8T6单片机之间的无线串口通信,文章提供原理,源码,测试效果图,测试工程下载: 目录 传输不规范问题: 串口通信资源: 单个串口资源理解: 单片机串口资源&#xf…

ModaHub魔搭社区:Milvus Cloud向量数据库不可小觑

向量数据库不可小觑 事实上,向量数据库并不是一个新的数据库技术,只是一直以来并没有什么亮眼的技术突破,因此显得有点“籍籍无名”。然而,当向量检索找到典型应用场景,成为普遍需求后,向量数据库的真正价值才日益凸显。 云和恩墨创始人,中国数据库联盟(ACDU) 主席盖…

[ Docker ] 部署 nps 和 npc 实现内网穿透

nps 原作者已停止维护,现在用 yisier1/nps 云主机上运行 nps 创建目录 mkdir -p /root/docker/nps mkdir /root/repo下载必要文件 Docker 镜像 docker pull yisier1/npsGit 仓库 git clone https://github.com/yisier/nps.git /root/repo cp -r /root/repo/nps…

【密码学】维京密码

维京密码 瑞典罗特布鲁纳巨石上的图案看起来毫无意义,但是它确实是一种维京密码。如果我们注意到每组图案中长笔画和短笔画的数量,将得到一组数字2、4、2、3、3、5、2、3、3、6、3、5。组合配对得到24、23、35、23、36、35。现在考虑如图1.4所示的内容&a…

yolov5部署 单线程与多线程对比

单线程 部署代码可参考&#xff1a; Yolov5 ONNX Runtime 的 C部署_爱钓鱼的歪猴的博客-CSDN博客 main.cpp #include "detector.h" #include <chrono> using namespace std;// 识别线程 void *detect_thread_entry(void *para){}int main(int argc, char *ar…

分布式应用:Zabbix监控MariaDB

目录 一、理论 1.Zabbix监控MariaDB 二、实验 1.Zabbix监控MariaDB 一、理论 1.Zabbix监控MariaDB &#xff08;1&#xff09;环境 zabbix服务端&#xff1a;192.168.204.214 zabbix客户端&#xff1a;192.168.204.215 &#xff08;2&#xff09;MareaDB安装 安装 za…

文献阅读:AnnoLLM: Making Large Language Models to Be Better Crowdsourced Annotators

文献阅读&#xff1a;AnnoLLM: Making Large Language Models to Be Better Crowdsourced Annotators 1. 文章简介2. 方法介绍3. 实验考察 1. 实验结果2. 消解实验3. Consistency & Stability 4. 结论 & 思考 文献链接&#xff1a;https://arxiv.org/abs/2303.16854 …

STM32F429IGT6使用CubeMX配置SPI通信(W25Q256芯片)

1、硬件电路 需要系统性的看一下W25Q256芯片手册 2、设置RCC&#xff0c;选择高速外部时钟HSE,时钟设置为180MHz 3、配置SPI 4、生成工程配置 5、相关代码 #define sFLASH_ID 0XEF4019 // W25Q256#define SPI_FLASH_PageSize 256 #define SPI_FLASH_PerWritePageSize 256#def…

爬虫小白-如何辨别请求头referer/origin反爬

目录 一、网站分析二、最终代码一、网站分析 1、网站,研究这块数据从哪个接口来的 2、反爬参数:请求头referer/origin校验和x-api-key 3、详细分析流程,看b站十一姐时一视频, 或者知识星球时光漫漫图文文章 二、最终代码 # -*- coding: utf-8 -*- # @Time : 2023-08-13

为了监控上厕所次数,我开发了一个软件

背景 最近整了一个好玩的东西&#xff0c;一个快捷指令&#xff0c;实现点击之后显示当前的日期&#xff0c;同时后台将这个时间记录到一个文件里。文件在icloud上&#xff0c;实现多个设备的同步。话不多说&#xff0c;先看看效果吧。 这个是我的“软件”图标&#xff1a; 怎…

网络安全 Day30-容器架构上

容器架构上 1. 容器架构1.1 什么是容器1.2 容器 vs 虚拟机(化) :star::star:1.3 Docker极速上手指南1&#xff09;使用rpm包安装docker2) docker下载镜像加速的配置3) 载入镜像大礼包&#xff08;老师资料包中有&#xff09; 1.4 Docker使用案例1&#xff09; 案例01&#xff1…

第12集丨Vue 江湖 —— 内置指令

目录 一、v-text二、v-html2.1 基本使用2.2 cookie原理2.2.1 登入成功后cookies的信息2.2.2 手动增加cookie值2.2.3 cookie edit 三、v-cloak3.1 案例 四、v-once五、v-pre 到本节为止&#xff0c;我们学过的指令: v-bind &#xff1a;单向绑定解析表达式v-model &#xff1a;…

idea生成springboot单元测试用例

1、找到需要生成单元测试的类型&#xff0c;右键Go To -> Test 2、选择JUnit4 和勾选需要测试的方法 3、查看自动生成的文件 public class CategoryMapperTest {Testpublic void findById() {}Testpublic void queryById() {} } 4、添加测试代码 RunWith(SpringRunner.cla…

【JavaEE】懒人的福音-MyBatis框架—[单表]增删改查等常规操作

【JavaEE】MyBatis框架要点总结&#xff08;2&#xff09; 文章目录 【JavaEE】MyBatis框架要点总结&#xff08;2&#xff09;1. 单表查看操作1.1 (条件查询)通过id查找用户1.1.1 接口上声明方法1.1.2 xml文件中去实现方法1.1.3 测试 1.2 传递参数的重点问题&#xff1a;sql注…

【LeetCode周赛】LeetCode第358场周赛

LeetCode第358场周赛 数组中的最大数对和翻倍以链表形式表示的数字限制条件下元素之间的最小绝对差 数组中的最大数对和 给你一个下标从0开始的整数数组nums。请你从nums中找出和最大的一对数&#xff0c;且这两个数数位上最大的数字相等。 返回最大和&#xff0c;如果不存在满…

手机商城网站的分析与设计(论文+源码)_kaic

目录 摘 要 1 1 绪论 2 1.1选题背景意义 2 1.2国内外研究现状 2 1.2.1国内研究现状 2 1.2.2国外研究现状 3 1.3研究内容 3 2 网上手机商城网站相关技术 4 2.1.NET框架 4 2.2Access数据库 4 2.3 JavaScript技术 4 3网上手机商城网站分析与设…

基于grpc从零开始搭建一个准生产分布式应用(3) - GRPC实现

本章开始会进入GRPC子专题&#xff0c;先实现前面章节中提到的例子。然后就使用的知识点展开全面的描述。本章代码任务&#xff1a;1、实现一个简单的GRPC服务&#xff1b;2、实现GRPC拦截器。 本章的代码承接上一章的代码进行迭代。因模块间存在相互依赖关系&#xff0c;读者一…