【退役之重学 Java】初步认识 AQS

一、AQS 是什么

  • Abstract Queued Synchronizer ,翻译过来就是“抽象的排好队的同步器”。 AQS 是一个用来构建锁和同步器的框架。
  • 是用来构建锁或者其他同步器组件的重量级基础框架及整个JUC体系的基石,通过内置的FIFO队列来完成线程获取资源的排队工作,并通过一个int类型变量表示持有锁的状态。

二、AQS 有什么用

  • 使用 AQS 能简单高效的构造出大量被广泛应用的同步器,比如 ReentrantLock,Semaphore,ReentrantReadWriteLock,SynchronousQueue,FutureTask等等,都是基于 AQS 的。
  • 我们也可以使用 AQS 轻松构造出符合特定需求的同步器。
  • 加锁会导致阻塞,有阻塞就需要排队,实现排队必然需要有某种形式的队列(CLH)来进行管理

三、AQS 的核心思想

  • 如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,
  • 并且将共享资源设置为锁定状态。
  • 如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制
  • 这个机制是 AQS 使用 CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。
  • CLH 是一个虚拟的双向FIFO队列,AQS 将每个请求共享资源的线程封装成Node 节点,并放入CLH
  • AQS 使用一个volatile 的 int 类型的变量来表示同步状态,通过内置的FIFO队列来完成资源获取的排队工作将每条要去抢占资源的线程封装成一个Node节点来实现锁的分配,通过CAS完成对State值的修改

四、AQS 基本结构

在这里插入图片描述

五、AQS 怎么用

  • 创建任一基于AQS实现的同步器
  • 创建多个线程,并分别使用同步器的 lock 和 unlock 方法
  • 会发现,这些线程是一个一个执行的,而非一起执行的,说明锁成功了。

六、进一步理解锁和同步器的关系

  • 锁,面相锁的使用者,定义了程序员和锁交互的使用层API
  • 同步器,面相锁的实现者,

七、源码分析

  1. Lock --> Syn -----> AQS,所以Lock 最终继承的是AQS
  2. lock(),acquire(),tryAcquire(arg),addWaiter(Node.EXCLUSIVE),addQueued(addWaiter(Node.EXCLUSIVE),arg)
    在这里插入图片描述
  3. head和tail
    • 是什么?
      head 和 tail 分别是头指针和尾指针,分别指向队列中的头节点和尾节点
    • 有什么用?
      方便出队和入队操作,也方便逻辑判断(暂时是这么理解的)
  4. 哨兵节点有什么用?
    队列中的哨兵节点在并发编程中起到了重要的作用。哨兵节点是一种特殊的节点,通常用于帮助管理和控制并发队列的行为。在使用队列实现同步器时,哨兵节点可以用来简化逻辑提高效率确保线程安全
  5. 确实有点复杂,但我感觉不应该去理解源码的每一行代码,而应该从整体设计思想去理解就好了,以后有机会自己实现一个简陋的example。
  6. 出队操作:第一个真实节点B抢占资源成功,哨兵节点出队,B变成新的哨兵节点

参考博客 一文让你彻底搞懂AQS(通俗易懂的AQS)
声明:仅用于学习,不做其他用途。本文对所引用的博客,进行了摘抄、整理,其中AQS 的知识点并不详尽,希望未来有机会能够更加深入地讲解它。


扩展

一、可重入锁

  • 可重入锁,又名递归锁。是指在同一个线程,在外层方法获取锁的时候,再进入线程的内层方法时,会自动获取锁(前提,锁对象得是同一个对象),不会因为之前已经获取过还没释放而阻塞
  • Java 中 ReentrantLock 和 Synchronized 都是可重入锁
  • 可重入锁的一个优点是可以一定程度避免死锁
  • 一句话概括:同一个线程可以多次获得属于自己的同一把锁,一定程度避免死锁

二、 LockSupport

  1. 是什么
    LockSupport 用于创建锁和其他同步类的基本线程阻塞原语。
  2. 有什么用
    • 对于原有锁支持线程等待唤醒机制(wait/nofify)的加强、改良版
    • LockSupport 的 park()和 unpark()的作用分别是阻塞线程和解除阻塞线程
    • 两个三角形:
      • (synchronized,wait,notify)
      • (lock,await,signal)
  3. 核心思想
    • LockSupport 使用了一种名为 Permit (许可)的概念来做到阻塞和唤醒线程的功能,每个线程都有一个许可(permit),permit 只有两个值1和0,默认为零
    • 可以把许可看成一种(0,1)信号量(Semaphore),但是与Semaphore 不同的是,许可的累加上限是1
  4. 怎么用
    • LockSupport.park() 阻塞
    • LockSupport.unpark(a) 唤醒啊
    • 什么叫阻塞,什么叫唤醒?
    • 阻塞就是说,在那一步线程就转换为“等待执行”的状态
    • 唤醒就是说,让线程继续执行
    • unpark()可以在park()之前执行
  5. 优点
    LockSupport 是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,阻塞之后也有对应的唤醒方法。归根结底,LockSupport 调用 Unsafe 中的native 代码。
  6. 为什么可以先唤醒线程后阻塞线程?
    因为unpark 获得了一个凭证,之后,在调用 park 方法,就可以名正言顺的凭证消费,故不会阻塞。

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

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

相关文章

【linux软件基础知识】如何使用 run_list 字段将任务放入就绪队列中

在给定的代码片段中,struct task_struct 表示内核中任务或进程的进程控制块 (PCB)。 run_list 字段的类型为 struct list_head,这表明它是链表实现的一部分。 run_list字段在Linux内核中常用来表示任务在调度队列中的位置,例如就绪队列或各种优先级队列。 init_task是一个…

第100+7步 ChatGPT文献复现:ARIMA-GRNN预测出血热

基于WIN10的64位系统演示 一、写在前面 这一次,我们来解读ARIMA-GRNN组合模型文章,也是老文章了: 《PLoS One》杂志的2015年一篇题目为《Comparison of Two Hybrid Models for Forecasting the Incidence of Hemorrhagic Fever with Renal…

树莓派、ubuntu低版本python3安装库

如果遇到树莓派中自带低版本python3,又不想额外去安装python3时,可能会遇到版本过低,无法安装库的情况,以下用我实际情况举例解决方案。 本次遇到的问题是树莓派低版本中,python3为3.7.3,需要安装numpy&am…

基于STC12C5A60S2系列1T 8051单片机实现一主单片机与一从单片机进行双向串口通信功能

基于STC12C5A60S2系列1T 8051单片机实现一主单片机与一从单片机进行双向串口通信功能 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机串口通信介绍STC12C5A60S2系列1T 8051单片机串口通信的结构基于STC12C5A60S2系列1T 8051单片机串口通信的特殊功能寄存器…

数据结构与算法===递归

文章目录 定义适用场景爬楼梯代码实现 小结 定义 递归(Recursion)是指函数的自身调用。 这个算法演变为了程序员之间的梗,所表达的意思近似于“套娃”,表示不断重复引用别人的话从而产生循环。 适用场景 这个应该很多的,像一些树的遍历&am…

Java | Leetcode Java题解之第84题柱状图中最大的矩形

题目&#xff1a; 题解&#xff1a; class Solution {public int largestRectangleArea(int[] heights) {int n heights.length;int[] left new int[n];int[] right new int[n];Arrays.fill(right, n);Deque<Integer> mono_stack new ArrayDeque<Integer>();f…

数据结构与算法学习笔记三---队列的顺序表示和实现(C语言)

目录 前言 1.顺序队列的描述 2.队列的顺序表示和实现 1.定义 2.初始化 3.销毁 4.清空 5.空队列 6.队列长度 7.获取队头 8.入队 9.出队 10.遍历队列 11.完整代码 前言 本篇博客介绍栈和队列的表示和实现。 1.顺序队列的描述 图1.顺序队列的描述 2.队列的顺序表示…

如何根据招聘信息打造完美简历

如何根据招聘信息打造完美简历 招聘信息分析简历调整策略个性化与关键词结语 在求职过程中&#xff0c;简历是第一块敲门砖。它不仅展示了你的专业技能和工作经验&#xff0c;还体现了你对所申请职位的理解和热情。然而&#xff0c;如何从招聘信息中提炼关键点&#xff0c;打造…

苹果电脑MAC清理系统空间工具CleanMyMacX4.15.3中文版下载

苹果电脑以其出色的性能、优雅的设计和高效的操作系统而受到许多用户的喜爱。然而&#xff0c;随着时间的推移和使用量的增加&#xff0c;你可能会发现你的Mac开始变得缓慢和响应迟缓。这通常是因为硬盘空间被大量占用&#xff0c;影响了系统的整体性能。幸运的是&#xff0c;有…

mysql管理

数据库服务管理 安装完成后,启动mysql服务器systemctl start mysqld然后查看mysql状态systemctl status mysqld 发现报错&#xff0c;因为centos不再支持MySQL数据库&#xff0c;安装mariadb代替 yum install –y mariadb-server 会在 /var/log/mysqld.log文件中会自动生成…

Android 13 系统自定义安全水印

效果 源码实现 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public final void showSafeModeOverlay() {View v LayoutInflater.from(mContext).inflate(com.android.internal.R.layout.safe_mode, null);WindowManager.Layout…

CSS滑动门

CSS滑动门使各种特殊形状的背景能够自动拉伸滑动&#xff0c;以适应元素内部的文本内容&#xff0c;其原理是&#xff1a;利用CSS精灵和盒子撑开宽度适应不同字数的导航栏。 特点&#xff1a; 1.可以根据导航字数自动调节宽度&#xff1b; 2.可以以简单的背景图实现炫彩的导航条…

NSS题目练习2

[LitCTF 2023]我Flag呢&#xff1f; 打开题目后查看源码即可发现flag [第五空间 2021]WebFTP 看到提示&#xff0c;首先想到用dirsearch扫描链接&#xff0c;看是否存在git泄露 发现存在git泄露&#xff0c;用githack解决 克隆提示目录为空&#xff0c;说明不正确&#xff0c…

前端工程化,前端监控,工作流,部署,性能

开发规范 创建项目的时候&#xff0c;配置下 ESlint&#xff0c;stylelint&#xff0c; prettier&#xff0c; commitlint 等; ESLint 主要功能&#xff1a; ESLint 是一个静态代码检查工具&#xff0c;用于在 JavaScript 代码中识别和报告模式。它的目标是提供一个插件化的 …

ios 开发如何给项目安装第三方库,以websocket库 SocketRocket 为例

1.brew 安装 cococapods $ brew install cocoapods 2、找到xcode项目 的根目录&#xff0c;如图&#xff0c;在根目录下创建Podfile 文件 3、在Podfile文件中写入 platform :ios, 13.0 use_frameworks! target chat_app do pod SocketRocket end project ../chat_app.x…

网安面经之文件上传漏洞

一、文件上传漏洞 1、文件上传漏洞的原理&#xff1f;危害&#xff1f;修复&#xff1f; 原理&#xff1a;⽂件上传漏洞是发⽣在有上传功能的应⽤中&#xff0c;如果应⽤程序对⽤户上传的⽂件没有控制或者存在缺陷&#xff0c;攻击者可以利⽤应⽤上传功能存在的缺陷&#xff…

JavaScript之数据类型(3)——object进阶

前言&#xff1a; 利用基础知识来构建对象会发现十分复杂&#xff0c;我们可以结合其他的知识点来为我们object的构建进行优化。 <1>工厂法&#xff1a; 基本格式&#xff1a; function creatObject(属性值1,属性值2,属性值3,...,属性值n) {var 对象名 new Object();对…

如何在idea里进行设置实现快捷键自动生成序列化版本号

问题描述&#xff1a; IntelliJ IDEA 提供了强大的代码生成功能&#xff0c;可以自动为实现了 Serializable 接口的类生成 serialVersionUID 字段。以下为具体操作步骤&#xff0c;希望对大家有帮助&#xff01; 步骤 1&#xff1a;确保类实现了 Serializable 接口 首先&…

【Android】Kotlin学习之数据容器 -- 集合

一. 定义 List : 是一个有序列表, 可通过下标访问元素. 元素可以在list中出现多次, 元素可重复 Set : 是元素唯一的集合, 一般来说Set中元素的顺序并不重要, 无序集合. Map : 是一组键值对, 键是唯一的, 每个键刚好映射到一个值, 值可以重复 二. 集合创建 三. 示例 mutabl…

通过linux花里胡哨的控制台,学习linux基础命令

今天这个B我装定了&#xff01; 前言命令集 开始1、cowsay &#xff08;让牛说话&#xff0c;够无聊的&#xff0c;但牛说的话是你输入的&#xff0c;细思极恐&#xff01;&#xff09;Debian/Ubuntu 安装命令&#xff1a;RHEL/CentOS/Fedora 安装&#xff1a;运行解释 2、fort…