并发编程12:AQS

news2024/12/29 8:04:51

文章目录

  • 12.1 前置知识
  • 12.2 AQS入门级别理论知识
    • 12.2.1 是什么?
    • 12.2.2 AQS为什么是JUC内容中最重要的基石
    • 12.2.3 能干嘛?
    • 12.2.4 小总结
  • 12.3 AQS源码分析前置知识储备
    • 12.3.1 AQS内部体系架构图
    • 12.3.2 AQS内部体系架构----AQS自身
    • 12.3.1 AQS内部体系架构----内部类Node
  • 12.4 AQS源码深度讲解和分析
    • 12.4.1 ReentrantLock的原理
    • 12.4.2 从最简单的lock方法开始看看公平和非公平
    • 12.4.3 以非公平锁ReentrantLock()为例作为突破走起---方法lock()
    • 12.4.4 unlock()

AQS:AbstractQueuedSynchronizer

12.1 前置知识

  • 公平锁和非公平锁

    • 公平锁:锁被释放以后,先申请的线程先得到锁。性能较差一些,因为公平锁为了保证时间上的绝对顺序,上下文切换更频繁
    • 非公平锁:锁被释放以后,后申请的线程可能会先获取到锁,是随机或者按照其他优先级排序的。性能更好,但可能会导致某些线程永远无法获取到锁
  • 可重入锁

    • 也叫做递归锁,指的是线程可以再次获取自己的内部锁,比如一个线程获取到了对象锁,此时这个对象锁还没有释放,当其想再次获取这个对象锁的时候还是可以获取的,如果不可重入的话,会导致死锁。
  • 自旋思想

    • 当线程请求锁时,如果锁已经被其他线程持有,那么该线程会不断地重试获取锁,而不是被挂起等待,这种不断尝试获取锁的行为称为自旋
  • LockSupport

    • 一个工具类,用于线程的阻塞和唤醒操作,类似于wait()和notify()方法,但是更加灵活和可控
    • 提供了park()和unpark()两个静态方法用于线程阻塞和唤醒操作。
    • 优点在于可以在任意时刻阻塞和唤醒线程而不需要事先获取锁或监视器对象。
  • 数据结构之双向链表

    • 双向链表(Doubly Linked List)是一种常见的数据结构,它是由一系列结点(Node)组成的,每个结点包含三个部分:数据域、前驱指针和后继指针。其中,数据域存储结点的数据,前驱指针指向前一个结点,后继指针指向后一个结点。通过这种方式,双向链表可以实现双向遍历和插入、删除操作。
  • 设计模式之模板设计模式

    • 模板设计模式是一种行为型设计模式,定义了一种算法的框架,并将某些步骤延迟到子类中事先,这种设计模式的主要目的是允许子类在不改变算法结构的情况下重新定义算法中的某些步骤。
    • 优点是能够提高代码复用性和可维护性。

12.2 AQS入门级别理论知识

12.2.1 是什么?

抽象的队列同步器

img

技术解释

  • 是用来实现锁或者其他同步器组件的公共基础部分的抽象实现
  • 是重量级基础框架及整个JUC体系的基石,只要用于解决锁分配给”谁“的问题。
  • 整体就是一个抽象的FIFO队列来完成资源获取线程的排队工作,并通过一个int类变量表示持有锁的状态

img

img

12.2.2 AQS为什么是JUC内容中最重要的基石

  • 和AQS有关的
    img

  • ReentrantLock
    img

  • CountDownLatch
    img

  • ReentrantReadWriteLock
    img

  • Semaphoreimg

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

    • 锁,面向锁的使用者:定义了程序员和锁交互的使用层API,隐藏了实现细节,你调用即可
    • 同步器,面向锁的实现者:Java并发大神DoungLee,提出了统一规范并简化了锁的实现,将其抽象出来,屏蔽了同步状态管理、同步队列的管理和维护、阻塞线程排队和通知、唤醒机制等,是一切锁和同步组件实现的----公共基础部分

12.2.3 能干嘛?

加锁会导致阻塞------有阻塞就需要排队,实现排队必然需要队列

  • 抢到资源的线程直接使用处理业务,抢不到资源的必然涉及一种排队等候机制。抢占失败的线程继续去等待(类似于银行办理窗口都满了,暂时没有受理窗口的顾客只能去候客区排队等待),但等候线程仍然保留获取锁的可能且获取锁流程仍在继续(候客区的顾客也在等着叫号,轮到了再去受理窗口办理业务)

  • 既然说到了排队等候机制,那么就一定会有某种队列形成,这样的队列是什么数据结构呢?

    • 如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列中,这个队列就是AQS同步队列的抽象表现。它将要请求共享资源的线程及自身的等待状态封装成队列的节点对象(Node),通过CAS、自旋以及LockSupport.park()的方式,维护着state变量的状态,使其达到同步的状态。 img

12.2.4 小总结

AQS同步队列的基本结构

img

12.3 AQS源码分析前置知识储备

12.3.1 AQS内部体系架构图

img

12.3.2 AQS内部体系架构----AQS自身

  • AQS的int类型变量state

    • AQS的同步状态State成员变量
      img

    • 银行办理业务的受理窗口状态

      • 零就是没人,自由状态可以去办理
      • 大于等于1,有人占用窗口,等着去
  • AQS的CLH队列

    • CLH(三个大牛的名字组成)队列为一个双向队列img

    • 银行候客区的等待顾客

  • 小总结

    • 有阻塞就需要排队,实现排队必然需要队列
    • State变量+CLH双端队列

12.3.1 AQS内部体系架构----内部类Node

  • Node的int变量

    • Node的等待状态waitState成员变量

      img

    • 说人话

      • 等候区其他顾客(其他线程)的等待状态
      • 队列中每个排队的个体就是一个Node
  • Node此类的讲解

    • 内部结构
      img

    • 属性说明img

12.4 AQS源码深度讲解和分析

12.4.1 ReentrantLock的原理

Lock接口的实现类,基本都是通过聚合了一个队列同步器的子类完成线程访问控制的

img

12.4.2 从最简单的lock方法开始看看公平和非公平

img

img

img

img

公平锁和非公平锁的lock()方法唯一的区别就在于公平锁在获取同步状态时多了一个限制条件:hasQueuedPredecessors()-----公平锁加锁时判断等待队列中是否存在有效节点的方法

12.4.3 以非公平锁ReentrantLock()为例作为突破走起—方法lock()

对比公平锁和非公平锁的tryAcquire()方法的实现代码,其实差异就在于非公平锁获取锁时比公平锁中少了一个判断**!hasQueuedPredecessors()**,hasQueuedPredecessors()中判断了是否需要排队,导致公平锁和非公平锁的差异如下:

  • 公平锁:公平锁讲究先来后到,线程在获取锁时,如果这个锁的等待队列中已经有线程在等待,那么当前线程就会进入到等待队列中;
  • 非公平锁:不管是否有等待队列,如果可以获取到锁,则立刻占有锁对象。也就是说队列的第一个排队线程苏醒后,不一定就是排头的这个线程获得锁,它还需要参加竞争锁(存在线程竞争的情况下),后来的线程可能不讲武德插队夺锁了。

img

img

正式开始源码解读:

  • lock()
    img
    img

  • acquire()
    img

  • tryAcquire(arg)
    img

    • return false:继续推进条件,走下一个方法
    • return true:结束
  • addwaiter(Node.EXCLUSIVE)
    img

    • 注意:在双向链表中,第一个节点为虚节点(也叫做哨兵节点),其实不存储任何信息,只是占位。真正的第一个有数据的节点,是从第二个节点开始的
    • 假如此时有线程C进入:img
  • acquireQueued(addWeiter(Node.EXCLUSIVE), arg)-----坐稳队列
    img

12.4.4 unlock()

在这里插入图片描述

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

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

相关文章

一、H3C-NE实验-抓包实验

实验一:抓包实验(PING包) 实验拓扑结构图 1. 修改设备名称 步骤1:启动设备 步骤2:在路由器1,进入系统视图,并修改设备名称为R1 步骤3:在路由器2,进入系统视图&#xf…

【Java|基础篇】类和对象

文章目录 1. 前言2. 什么是面向对象3. 类的定义4. 类的实例化5. 对象的构造及初始化6. this引用7. 总结 1. 前言 本篇文章主要讲解了下面三个问题 类的定义和实例化构造方法this关键字 2. 什么是面向对象 众所周知面向过程和面向对象是两种重要的编程思想,而Java是属于面向…

C语言函数大全-- v 开头的函数

C语言函数大全 本篇介绍C语言函数大全-- v 开头的函数 1. va_start 1.1 函数说明 函数声明函数功能void va_start(va_list ap, last_arg);用于初始化一个 va_list 类型的变量,使其指向可变参数列表中的第一个参数 参数: ap: 一个指向 va_…

我的创作纪念日(个人感悟)

昨天2023年5月10日是我成为创作者的第128天纪念日,感谢CSDN官方的纪念信让我铭记这特殊的一天。 机缘 要说与CSDN的初次相遇,还是2022年的高考结束完的暑假,当时对于大学的学习没有什么概念,当初的高考志愿报的有计算机相关的专…

spring集成mybatis的原理

spring是怎样和mybatis继承的? 在idea里点mapper.queryOne()直接跳到了接口或xml,它究竟是怎样利用jdbc执行的? 我直接调用mapper.queryOne是怎么使用的sqlsession?怎么去connect的? mybatis是怎样根据mapper找到对应的…

【Java面试】Java并发基础(1)

文章目录 1. 可见性,有序性,原子性2. java中并发和并行3. 通常线程有哪几种使用方式? 1. 可见性,有序性,原子性 可见性(Visibility): 指一个线程修改了共享变量的值之后,其他线程能…

学习网络通信必备的DNS解析和Socket通信知识

OkHttp是一个开源的网络请求框架,由Square公司开发。它通过封装Java底层的HttpURLConnection和Okio等库,提供一个简单易用的API,让开发人员能够方便地向服务器发送HTTP/HTTPS请求,支持异步请求和响应回调,并提供丰富的…

未来已来, 新能源与IT的技术碰撞;学习Android车载开发的必然趋势

Android工程师前景 Android车载工程师扮演着关键的角色,他们致力于将最新的Android技术和汽车技术相结合,为汽车行业提供优质的产品。随着越来越多的汽车制造商投资于智能汽车技术和车联网技术,Android车载工程师成为了一个越来越重要的职业…

MATLAB实现二维稳态导热

MATLAB实现二维稳态导热 一、理论基础二、代码实现 一、理论基础 步骤: Step.1 二维模型传热控制微分方程的确定,具体推导可以在任何一本传热学的书中找到。 d 2 T d x 2 d 2 T d y 2 0 \frac{d^{2}T}{dx^{2}}\frac{d^{2}T}{dy^{2}}0 dx2d2T​dy2d2T…

Ansible 自动化运维工具(一)——部署以及命令行模块

文章目录 一、 ansible 的概述1、ansible简介2.、官方网站3、ansible 的特点4、ansible的工作机制5、ansible的组成模块 二、ansible部署1、Asible的安装 三、ansible 命令行模块1、command 模块2、shell 模块3、cron 模块4、user 模块5、group 模块6、copy 模块7、file 模块8、…

【ros/ros2】ros1和ros2的区别-要点记录

dds data distribution service,数据分发服务 rcl ros client libraries,ros客户端库文件 rmw ros middle ware interface,ros中间件接口 lcn life cycle node,生命周期节点,受控节点 lmn lifecycle manageme…

C++二叉树递归方法存入和三种递归方法读出(前序,中序,后序)

#include <stdio.h> #include <malloc.h> typedef struct op //定义子树结构 { int data; struct op *lchild; struct op *rchild; }treestruct; treestruct *createtree() //这里这种表达形式意思是bittree类型的函数 最终要返回bitt…

【Linux】版本管理器Git

&#x1f3d6;️作者&#xff1a;malloc不出对象 ⛺专栏&#xff1a;Linux的学习之路 &#x1f466;个人简介&#xff1a;一名双非本科院校大二在读的科班编程菜鸟&#xff0c;努力编程只为赶上各位大佬的步伐&#x1f648;&#x1f648; 目录 前言一、Git是什么二、Git有什么…

开源C#代码生成器,专注.NET,Sqlserver,最简单,最干净,支持自编码的开源工具,SmartSoftHelp 开发辅助优化工具

开源C#代码生成器&#xff0c;专注.NET&#xff0c;Sqlserver&#xff0c;最简单&#xff0c;最干净&#xff0c;支持自编码的开源工具&#xff0c;SmartSoftHelp 开发辅助优化工具&#xff01; 下载地址&#xff1a;https://pan.baidu.com/s/1XLL_fLxVTw4erYZLj8-MzA?pwd888…

搭建python运行环境

安装Miniconda3 清华镜像 https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/ 下载 安装 next————agree————这俩选哪个都行&#xff0c;他选的第二个————安装路径———— 配置系统环境变量 Path miniconda3所在的路径 D:\Autils\miniconda3 Scri…

ChatGPT 最有可能取代哪些职业?

ChatGPT 的应用场景ChatGPT 最可能取代哪些职业&#xff1f;写在最后 ChatGPT 的应用场景 ChatGPT 的应用场景大体上可以归类为三大模块。 第一类是 代码相关 的任务场景。包含程序语言之间的相互转换&#xff08;如 python 转 java&#xff09;、程序命令的生成、代码 bug 的…

Gateway新一代网关

Gateway功能&#xff1a;路由 过滤 一、概述 官网地址 不使用网关存在的问题&#xff1a; 1、客户端需要记录不同微服务地址&#xff0c;增加客户端的复杂性 2、每个后台微服务都需要认证 3、http 发请求&#xff0c;涉及到跨域 4、后台新增微服务&#xff0c;不能动态知道地…

【持久层框架】mybatis-plus超详细讲解

文章目录 一、简介二、愿景三、特性四、支持数据库五、快速指南步骤1、创建数据库 mybatis_plus2、导入相应的依赖3、连接数据库4、编写代码5、小结 六、配置日志七、常用注解八、CRUD扩展Insert 插入参数说明主键生成策略分布式系统唯一id生成雪花算法主键自增 更新操作参数说…

纪念一下自己做的第一款开发板

文章目录 1. 硬件电路2. 成品展示3. 遇到的问题4. HelloWorld 前言&#xff1a;之前乐鑫搞活动白嫖了10个ESP32-S2模组&#xff0c;想着把它给利用了&#xff0c;然后先从一个开发板做起&#xff0c;等玩明白了再去做一些自己的设计&#xff0c;从网上找了一些资料就开始干&…

【★前后端的交互★】Servlet API

欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#xff1a;重难点★✔ 蓝色文字表示&#…