AQS简介、AQS实现原理、线程夺取锁失败 AQS队列的变化、线程被唤醒时 AQS队列的变化

AQS

  • AQS简介
  • AQS实现原理
    • 场景01-线程抢夺锁失败时,AQS队列的变化
    • 场景02-线程被唤醒时,AQS队列的变化

AQS简介

AQS(全称AbstractQueuedSynchronizer)即队列同步器。它是构建锁或者其他同步组件的基础框 架(如ReentrantLock、ReentrantReadWriteLock、Semaphore等)。AQS是JUC并发包中的核心基础组件,其本身是一个抽象类。理论上还是利用管程实现的,在AQS中,有一个volatile修饰的state,获取 锁的时候,会读写state的值,解锁的时候,也会读写state的值。所以AQS就拥有了volatile的happens- before规则。加锁与解锁的效果上与synchronized是相同的。

在这里插入图片描述
在这里插入图片描述
由类图可以看到,AQS是一个FIFO的双向队列,其内部通过节点head和tail记录队首和队尾元素,队列 元素的类型为Node。

在这里插入图片描述
在AQS中维持了一个单一的状态信息state,对于ReentrantLock的实现来说,state 可以用来表示当前线 程获取锁的可重入次数;AQS继承自AbstractOwnableSynchronizer,其中的exclusiveOwnerThread 变量表示当前共享资源的持有线程。

AQS实现原理

  1. AQS是一个同步队列,内部使用一个FIFO的双向链表,管理线程同步时的所有被阻塞线程。双向链表这种数据结构,它的每个数据节点中都有两个指针,分别指向直接后继节点和直接前驱节点。所以,从双向链表中的任意一个节点开始,都可以很方便地访问它的前驱节点和后继节点。
  2. 我们看下面的AQS的数据结构,AQS有两个节点head,tail分别是头节点和尾节点指针,默认为null。 AQS中的内部静态类Node为链表节点,AQS会在线程获取锁失败后,线程会被阻塞并被封装成Node加 入到AQS队列中;当获取锁的线程释放锁后,会从AQS队列中的唤醒一个线程(节点)。

在这里插入图片描述

场景01-线程抢夺锁失败时,AQS队列的变化

  1. AQS的head,tail分别代表同步队列头节点和尾节点指针,默认为null。
    在这里插入图片描述

  2. 当第一个线程抢夺锁失败,同步队列会先初始化,随后线程会被封装成Node节点追加到AQS队列 中。假设当前独占锁的的线程为ThreadA,抢占锁失败的线程为ThreadB。
    在这里插入图片描述
    在这里插入图片描述

场景02-线程被唤醒时,AQS队列的变化

ReentrantLock唤醒阻塞线程时,会按照FIFO的原则从AQS中head头部开始唤醒首个节点中线程。 head节点表示当前获取锁成功的线程ThreadA节点。
当ThreadA释放锁时,它会唤醒后继节点线程ThreadB,ThreadB开始尝试获得锁,如果ThreadB获得 锁成功,会将自己设置为AQS的头节点。ThreadB获取锁成功后,AQS变化如下:

  1. head指针指向ThreadB节点。
  2. 将原来头节点的next指向Null,从AQS中删除。
  3. 将ThreadB节点的prev指向Null,设置节点的thread=null。
    在这里插入图片描述

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

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

相关文章

Dell服务器iDRAC9忘记密码, 通过RACADM工具不重启 重置密码

系列文章目录 文章目录 系列文章目录前言一、RACADM工具二、linux环境1.解压安装RACADM工具测试RACADM工具重置iDRAC密码 Windows环境 前言 一、RACADM工具 RACADM工具 官网参考信息 https://www.dell.com/support/kbdoc/zh-cn/000126703/%E5%A6%82%E4%BD%95-%E9%87%8D%E7%BD…

web前端-------弹性盒子(2)

上一讲我们谈的是盒子的容器实行,今天我们来聊一聊弹性盒子的项目属性; *******************(1)顺序属性 order属性,用于定义容器中项目的出现顺序。 顺序属性值,为整数,可以为负数&#xff…

k8s-常用工作负载控制器(更高级管理Pod)

一、工作负载控制器是什么? 二、Deploymennt控制器:介绍与部署应用 部署 三、Deployment控制器:滚动升级、零停机 方式一: 通个加入健康检查可以,看到,nginx容器逐个被替代,最终每个都升级完成&…

算法学习——华为机考题库10(HJ64 - HJ69)

算法学习——华为机考题库10(HJ64 - HJ69) HJ64 MP3光标位置 描述 MP3 Player因为屏幕较小,显示歌曲列表的时候每屏只能显示几首歌曲,用户要通过上下键才能浏览所有的歌曲。为了简化处理,假设每屏只能显示4首歌曲&a…

幻兽帕鲁客户端存档文件 - 云上备份和恢复教程

本文将详细介绍如何将幻兽帕鲁游戏客户端的存档文件备份至云端,以及如何从云端恢复存档数据至本地。 一、游戏存档备份场景 幻兽帕鲁的游戏进度存储在电脑本地磁盘上,游戏中创建的每个世界都对应一个本地存档文件夹。在玩游戏过程中,客户端…

xlsx xlsx-style 使用和坑记录

1 安装之后报错 npm install xlsx --savenpm install xlsx-style --save Umi运行会报错 自己代码 import XLSX from "xlsx"; import XLSXStyle from "xlsx-style";const data [["demo1","demo2","demo3","demo4&quo…

linux中的gdb调试

gdb是在程序运行的结果与预期不符合时,可以使用gdb进行调试 注意:使用gdb调试时要在编译上加-g参数 gcc -g -c hello.c 启动gdb调试: gdb file 对gdb进行调试 设置运行参数: set args 可指定运行参数 show args 可以查…

群晖NAS开启FTP服务结合内网穿透实现公网远程访问本地服务

⛳️ 推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 文章目录 ⛳️ 推荐1. 群晖安装Cpolar2. 创建FTP公网地址3. 开启群晖FTP服务4. 群晖FTP远程连接5. 固定FTP公网地址6. 固定FTP…

【C语言】static关键字的使用

目录 一、静态本地变量 1.1 静态本地变量的定义 1.2 静态本地变量和非静态本地变量的区别 二、静态函数 2.1 静态函数的定义 2.2 静态函数与非静态函数的区别 三、静态全局变量 3.1 静态全局变量的定义 3.2 静态全局变量和非静态全局变量的区别 四、静态结构体变量 …

数据库管理phpmyadmin

子任务1-PHPmyadmin软件的使用 本子任务讲解phpmyadmin的介绍和使用操作。 训练目标 1、掌握PHPmyadmin软件的使用方法。 步骤1 phpMyAdmin 介绍 phpmyadmin是一个用PHP编写的软件工具,可以通过web方式控制和操作MySQL数据库。通过phpMyAdmin可以完全对数据库进行…

使用pandas将excel转成json格式

1.Excel数据 2.我们想要的JSON格式 {"0": {"raw_data1": "Sam","raw_data2": "Wong","raw_data3": "Good","layer": "12v1"},"1": {"raw_data1": "Lucy…

渗透测试练习题解析 2(CTF web)

题目均来自 BUUCTF 1、[极客大挑战 2019]Upload 1 考点:文件上传漏洞 进入靶场 一看就知道是考察文件上传漏洞,看源码有没有敏感信息 没有什么敏感信息,那我们试着按要求传一张图片看看结果,但是传了 png、jpg 类型的图片后发现上…