并发编程之深入理解AQS

目录

什么是AQS?

AQS的特性

AQS总结


什么是AQS?

       java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这些行为的抽象就是基于AbstractQueuedSynchronizer(简称AQS)实现的,AQS是一个抽象同步框架,可以用来实现一个依赖状态的同步器。

      JDK中提供的大多数的同步器如ReentrantLock, Semaphore、CountDownLatch等,都是基于AQS框架来实现的。(一般是通过一个内部类Sync继承AQS将同步器所有调用都映射到Sync对应的方法)以下是ReentrantLock的相关源码:

       通过以上图片我们可以看到ReentrantLock实现了Lock接口,然后内部类Sync继承了AbstractQueuedSynchronizer,所以说ReentrantLock也是基于AQS框架来实现的。

AQS的特性

1. 阻塞等待队列 2. 共享/独占 3. 公平/非公平 4. 可重入 5. 允许中断

AQS内部维护属性volatile int state

state表示资源的可用状态

State三种访问方式:

getState()、setState()、compareAndSetState()

AQS定义两种资源共享方式

Exclusive-独占,只有一个线程能执行,如ReentrantLock

Share-共享,多个线程可以同时执行,如Semaphore/CountDownLatch

AQS定义两种队列

同步等待队列: 主要用于维护获取锁失败时入队的线程

条件等待队列: 调用await()的时候会释放锁,然后线程会加入到条件队列,调用signal()唤醒的时候会把条件队列中的线程节点移动到同步队列中,等待再次获得锁。

同步等待队列

        AQS当中的同步等待队列也称CLH队列,CLH队列是Craig、Landin、Hagersten三人发明的一种基于双向链表数据结构的队列,是FIFO先进先出线程等待队列,Java中的CLH队列是原CLH队列的一个变种,线程由原自旋机制改为阻塞机制。

AQS 依赖CLH同步队列来完成同步状态的管理:

1. 当前线程如果获取同步状态失败时,AQS则会将当前线程已经等待状态等信息构造成一个节点(Node)并将其加入到CLH同步队列,同时会阻塞当前线程。

2. 当同步状态释放时,会把首节点唤醒(公平锁),使其再次尝试获取同步状态。

3. 通过signal或signalAll将条件队列中的节点转移到同步队列。(由条件队列转化为同步队列)

条件等待队列

AQS中条件队列是使用单向列表保存的,用nextWaiter来连接

1. 调用await方法阻塞线程。

2. 当前线程存在于同步队列的头结点,调用await方法进行阻塞(从同步队列转化到条件队列)。

 Condition接口详解
       condition条件等待队列用于支持线程的条件等待和唤醒操作。当一个线程在某个条件上等待时(使用await方法),它将会释放持有的锁,并进入条件等待队列,等待其他线程通过signal或signalAll方法来唤醒它。以下是await和signal方法的相关解析:

await()方法

      当线程调用await方法时,它首先会检查当前线程是否持有锁。如果线程没有持有锁,则会抛出IllegalMonitorStateException异常。持有锁的情况下会创建一个节点(Node对象)来表示当前线程,并将该节点加入到条件等待队列中(即将节点加入到Condition的等待队列中)。 线程会释放持有的锁,并进入等待状态,直到被唤醒。同时,线程会被阻塞在条件等待队列上的节点上,使其不再参与锁的竞争。当线程被唤醒时,它会重新尝试获取锁,并从await方法返回,继续执行后续代码。

signal/signalAll方法

       当线程调用signal方法时,它会将条件等待队列中的第一个节点从条件等待队列中移动到同步队列中(即移动到AQS的等待队列中),表示该线程有机会再次参与锁的竞争。


AQS总结

         AQS是多线程同步器,它是JUC包中多个组件的底层实现,如 Lock、 CountDownLatch、Semaphore等都用到了AQS. 从本质上来说,AQS 提供了两种锁机制,分别是排它锁和共享锁。 排它锁,就是存在多线程竞争同一共享资源时,同一时刻只允许一个线程访问该共享资源,也就是多个线程中只能有一个线程获得锁资源,比如Lock中的ReentrantLock可重入锁实现就是用到了 AQS中的排它锁功能。 共享锁也称为读锁,就是在同一时刻允许多个线程同时获得锁资源,比如 CountDownLatch和Semaphore都是用到了AQS中的共享锁功能。
        AQS采用了一个int类型的互斥变量state用来记录锁竞争的一个状态,0表示当前没有任何线程竞争锁资源,而大于等于1表示已经有线程正在持有锁资源。一个线程来获取锁资源的时候,首先判断state是否等于0,如果是(无锁状态),则把这个state更新成1,表示占用到锁。此时如果多个线程进行同样的操作,会造成线程安全问题。把阻塞的线程按照先进先出的原则加入到一个双向链表的结构中(同步等待队列),当获得锁资源的线程释放锁之后,会从双向链表的头部去唤醒下一个等待的线程再去竞争锁。另外关于公平性和非公平性问题,AQS的处理方式是,在竞争锁资源的时候,公平锁需要判断双向链表中是否有阻塞的线程,如果有,则需要去排队等待;而非公平锁的处理方式是,不管双向链表中是否存在等待锁的线程,都会直接尝试更改互斥变量state去竞争锁。

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

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

相关文章

WordPress后台仪表盘自定义添加删除概览项目插件Glance That

成功搭建WordPress站点,登录后台后可以在“仪表盘 – 概览”中看到包括多少篇文章、多少个页面、多少条评论和当前WordPress版本号及所使用的主题。具体如下图所示: 但是如果我们的WordPress站点还有自定义文章类型,也想在概览中显示出来应该…

【经验分享】美赛报名以及注册方法-以2024年美赛为例

1 进入美赛官网 首先点击COMAP的官网链接: https://www.comap.com/然后选择Contests目录下的MCM/ICM 选择 Learn More and Register 然后选择 register for contest 接下来开始注册环节,注册分为两个步骤:顾问(指导教师&#xf…

Jsqlparser简单学习

文章目录 学习链接模块访问者模式parser模块statement模块Expression模块deparser模块 测试TestDropTestSelectTestSelectVisitor 学习链接 java设计模式:访问者模式 github使用示例参考 测试 JSqlParser使用示例 JSqlParse(一)基本增删改…

GitHub API使用--获取GitHub topic

目录标题 技术简介申请token简单使用使用Java调用获取GitHub topic总结 技术简介 GitHub API是一个功能强大的工具,为开发者提供了访问和操作GitHub平台上资源的途径。无论是构建个人工具,集成自动化流程,还是开发应用程序,GitHu…

【Git】任何位置查看git日志

需求 现需要查看指定项目中的某个文件的 Git 日志。如有 项目代码 jflowable ,需要查看其下文件 D:\z_workspace\jflowable\src\main\java\com\xzbd\jflowable\controller\TestController.java 的日志。 分析 一般的思路是,进入 jflowable 项目&#…

ES 之索引和文档

本文主要介绍ES中的数据组成结构单元。 一、文档(Document) 1、概念 ES的数据存储单元是面向文档的,文档是所有数据存储,搜索的最小单元。 你可以把ES中的文档对应成mysql中的一条条数据记录。到时候你存进ES的数据就是一个个文档。 文档存入ES是序列…

BRC20通证的诞生与未来展望!如何导入bitget教程

BRC-20通证是什么? 嘿!你知道BRC-20通证吗?这可是比特币区块链上的超级明星!它们不依赖智能合约,而是把JSON代码刻在聪上,聪可是比特币的最小单位哦!就像在比特币的乐高积木上盖房子&#xff0…

dubbo入门案例!!!

入门案例之前我们先介绍一下:zookeeper。 Zookeeper是Apacahe Hadoop的子项目,可以为分布式应用程序协调服务,适合作为Dubbo服务的注册中心,负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只…

自动驾驶轨迹规划之碰撞检测(一)

欢迎大家关注我的B站: 偷吃薯片的Zheng同学的个人空间-偷吃薯片的Zheng同学个人主页-哔哩哔哩视频 (bilibili.com) 目录 1.碰撞检测的意义 2.安全走廊 3 计算几何 4 AABB与OBB 1.碰撞检测的意义 对于自动驾驶汽车或机器人的路径规划,碰撞检测是其…

Python 数据类型转换:数据世界的形态转换术

在 Python 中,数据类型转换是一项关键的技能。数据类型的转换使得我们能够在不同类型的数据之间进行转换和操作,提升了我们对数据的处理能力。本文将深入探讨 Python 中的数据类型转换,包括常见的数据类型、转换方法和使用技巧。 常见的数据类…

M1 MacOS下安卓虚拟化的最佳方案

categories: [VM] tags: MacOS VM 写在前面 一直想在桌面环境虚拟化安卓app, 但是看网上的推荐一直感觉不合胃口, 不是要花钱就是有广告, 想着找找开源的实现, 后来发现还是 Google 自家的产品用着舒服. 安装与配置 brew install android-studio然后随便开一个项目, 选默认…

通过Shell脚本登录MySQL,并执行MySQL命令

以下是一个通过Shell脚本登录MySQL 8并执行MySQL命令的示例: #!/bin/bash# MySQL服务器地址(如果在同一台机器上,可以是localhost或127.0.0.1) MYSQL_HOST"localhost"# MySQL服务器端口(默认为3306&#xf…

阿赵UE学习笔记——10、Blender材质和绘制网格体

阿赵UE学习笔记目录   大家好,我是阿赵。   之前介绍了虚幻引擎的材质和材质实例。这次来介绍一个比较有趣的内置的Blender材质。   在用Unity的时候,我做过一个多通道混合地表贴图的效果,而要做过一个刷顶点颜色混合地表和水面的效果。…

C#封装服务

C#封装服务 新建服务项目;重构 OnStart 和 OnStop using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Linq; using System.ServiceProcess; using System.Text; using S…

【Gradle】Maven-Publishing

使用Java开发完成一个模块或者一个基础框架需要提供给团队项目使用,这个时候有两种方式可提供,一是提供源码,二是提供编译构建好的jar包供使用,这个时候需要讲构建好的包发布到公司的私服(公司maven仓库)&a…

HCIP BGP(一)

任务: 1.R1上有两个环回,分别为192.168.1.0/24&192.168.2.0/24,只允许学到汇总&1.0 2.R7上有两个环回172.16.1.0/24&172.16.2.0/24,要求全部宣告,但是只有2.0可以通过 3.全网可达 拓扑图如下&#xff…

C语言经典算法之顺序查找算法

目录 前言 A.建议 B.简介 一 代码实现 二 算法时空复杂度 A.时间复杂度: B.空间复杂度: 三 优点和缺点 A.优点: B.缺点: 四 现实中的应用 前言 A.建议 1.学习算法最重要的是理解算法的每一步,而不是记住算…

常见的反爬虫风控 | 验证码风控

一.前言 在当今信息技术迅速发展的背景下,网站和在线服务面临着日益增长的自动化访问威胁,这些大多来自于各类爬虫程序。这种大量的自动化访问不仅对网站的正常运行构成压力,还可能导致敏感数据的泄露,甚至被用于不正当竞争和恶意…

多表关联查询

基本信息: 1.创建student和score表 CREATE TABLE student ( id INT(10) NOT NULL UNIQUE PRIMARY KEY , name VARCHAR(20) NOT NULL , sex VARCHAR(4) , birth YEAR, department VARCHAR(20) , address VARCHAR(50) ); 创建score表。SQL代码如下&#…

C++大学教程(第九版)5.15修改GradeBook

目录 题目 代码 运行命令(在控制台输入) 运行截图 题目 (修改GradeBook)修改图5.9~图5.11所示的 GradeBook 程序,使它计算一组成绩的平均成绩。 成绩A为4分,成绩B为3分,依次类推。 A:4 B:3…