小工具      在线工具  汉语词典  css  js  c++  java

12. AbstractQueuedSynchronizer之AQS

链表,数据结构,算法 额外说明

收录于:210天前

12.1 前置知识
● 公平锁和非公平锁
○ 公平锁:锁被释放以后,先申请的线程先得到锁。性能较差一些,因为公平锁为了保证时间上的绝对顺序,上下文切换更频繁
○ 非公平锁:锁被释放以后,后申请的线程可能会先获取到锁,是随机或者按照其他优先级排序的。性能更好,但可能会导致某些线程永远无法获取到锁
● 可重入锁
○ 也叫做递归锁,指的是线程可以再次获取自己的内部锁,比如一个线程获取到了对象锁,此时这个对象锁还没有释放,当其想再次获取这个对象锁的时候还是可以获取的,如果不可重入的话,会导致死锁。
● 自旋思想
○ 当线程请求锁时,如果锁已经被其他线程持有,那么该线程会不断地重试获取锁,而不是被挂起等待,这种不断尝试获取锁的行为称为自旋
● LockSupport
○ 一个工具类,用于线程的阻塞和唤醒操作,类似于wait()和notify()方法,但是更加灵活和可控
○ 提供了park()和unpark()两个静态方法用于线程阻塞和唤醒操作。
○ 优点在于可以在任意时刻阻塞和唤醒线程而不需要事先获取锁或监视器对象。
● 数据结构之双向链表
○ 双向链表(Doubly Linked List)是一种常见的数据结构,它是由一系列结点(Node)组成的,每个结点包含三个部分:数据域、前驱指针和后继指针。其中,数据域存储结点的数据,前驱指针指向前一个结点,后继指针指向后一个结点。通过这种方式,双向链表可以实现双向遍历和插入、删除操作。
● 设计模式之模板设计模式
○ 模板设计模式是一种行为型设计模式,定义了一种算法的框架,并将某些步骤延迟到子类中事先,这种设计模式的主要目的是允许子类在不改变算法结构的情况下重新定义算法中的某些步骤。
○ 优点是能够提高代码复用性和可维护性。

12.2 AQS入门级别理论知识
12.2.1 是什么?
抽象的队列同步器
在这里插入图片描述
技术解释
● 是用来实现锁或者其他同步器组件的公共基础部分的抽象实现
● 是重量级基础框架及整个JUC体系的基石,只要用于解决锁分配给”谁“的问题。
● 整体就是一个抽象的FIFO队列来完成资源获取线程的排队工作,并通过一个int类变量表示持有锁的状态

在这里插入图片描述
在这里插入图片描述
12.2.2 AQS为什么是JUC内容中最重要的基石
和AQS有关的
在这里插入图片描述
ReentrantLock
在这里插入图片描述
CountDownLatch
在这里插入图片描述
ReentrantReadWriteLock
在这里插入图片描述
Semaphore
在这里插入图片描述
● 进一步理解锁和同步器的关系
○ 锁,面向锁的使用者:定义了程序员和锁交互的使用层API,隐藏了实现细节,你调用即可
○ 同步器,面向锁的实现者:Java并发大神DoungLee,提出了统一规范并简化了锁的实现,将其抽象出来,屏蔽了同步状态管理、同步队列的管理和维护、阻塞线程排队和通知、唤醒机制等,是一切锁和同步组件实现的----公共基础部分

12.2.3 能干嘛?
加锁会导致阻塞------有阻塞就需要排队,实现排队必然需要队列
● 抢到资源的线程直接使用处理业务,抢不到资源的必然涉及一种排队等候机制。抢占失败的线程继续去等待(类似于银行办理窗口都满了,暂时没有受理窗口的顾客只能去候客区排队等待),但等候线程仍然保留获取锁的可能且获取锁流程仍在继续(候客区的顾客也在等着叫号,轮到了再去受理窗口办理业务)
● 既然说到了排队等候机制,那么就一定会有某种队列形成,这样的队列是什么数据结构呢?
○ 如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列中,这个队列就是AQS同步队列的抽象表现。它将要请求共享资源的线程及自身的等待状态封装成队列的节点对象(Node),通过CAS、自旋以及LockSupport.park()的方式,维护着state变量的状态,使其达到同步的状态。
在这里插入图片描述
12.2.4 小总结
AQS同步队列的基本结构
在这里插入图片描述
12.3 AQS源码分析前置知识储备
12.3.1 AQS内部体系架构图
在这里插入图片描述
2.3.2 AQS内部体系架构----AQS自身
● AQS的int类型变量state
○ AQS的同步状态State成员变量
在这里插入图片描述

○ 银行办理业务的受理窗口状态
■ 零就是没人,自由状态可以去办理
■ 大于等于1,有人占用窗口,等着去
● AQS的CLH队列
○ CLH(三个大牛的名字组成)队列为一个双向队列
在这里插入图片描述
○ 银行候客区的等待顾客
● 小总结
○ 有阻塞就需要排队,实现排队必然需要队列
○ State变量+CLH双端队列

● Node此类的讲解
○ 内部结构
在这里插入图片描述
属性说明
在这里插入图片描述
12.4 AQS源码深度讲解和分析
12.4.1 ReentrantLock的原理
Lock接口的实现类,基本都是通过聚合了一个队列同步器的子类完成线程访问控制的

在这里插入图片描述
12.4.2 从最简单的lock方法开始看看公平和非公平
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
公平锁和非公平锁的lock()方法唯一的区别就在于公平锁在获取同步状态时多了一个限制条件:hasQueuedPredecessors()-----公平锁加锁时判断等待队列中是否存在有效节点的方法
12.4.3 以非公平锁ReentrantLock()为例作为突破走起—方法lock()
对比公平锁和非公平锁的tryAcquire()方法的实现代码,其实差异就在于非公平锁获取锁时比公平锁中少了一个判断!hasQueuedPredecessors(),hasQueuedPredecessors()中判断了是否需要排队,导致公平锁和非公平锁的差异如下:
● 公平锁:公平锁讲究先来后到,线程在获取锁时,如果这个锁的等待队列中已经有线程在等待,那么当前线程就会进入到等待队列中;
● 非公平锁:不管是否有等待队列,如果可以获取到锁,则立刻占有锁对象。也就是说队列的第一个排队线程苏醒后,不一定就是排头的这个线程获得锁,它还需要参加竞争锁(存在线程竞争的情况下),后来的线程可能不讲武德插队夺锁了。
在这里插入图片描述
在这里插入图片描述
正式开始源码解读:
● lock()

在这里插入图片描述
在这里插入图片描述
acquire()

在这里插入图片描述
tryAcquire(arg)
在这里插入图片描述
○ return false:继续推进条件,走下一个方法
○ return true:结束
● addwaiter(Node.EXCLUSIVE)

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

在这里插入图片描述

. . .

相关推荐

额外说明

JS实现检查密码强度功能

编写一个JS函数,基于如下规则确定给定密码的强度。 目录 一、函数要求 二、示例输出 三、约束条件 四、程序代码 一、函数要求 1、如果只包含数字,而且少于 8 个字符,则为非常弱的密码。 2、如果只包含字母,而且少于 8 个字符,则为弱密码。 3、 如

额外说明

【MQ读书笔记之RabbitMQ】RabbitMQ消息队列面试题

1、什么是rabbitmq及其原理 采用AMQP高级消息队列协议的一种消息队列技术,最大的特点就是消费并不需要确保提供方存在,实现了服务之间的高度解耦 Broker:它提供一种传输服务,它的角色就是维护一条从生产者到消费者的路线,保证数据能按照指定的方式

额外说明

leetcode665(非递减序列:数组遍历)

给你一个长度为 n 的整数数组,请你判断在 最多 改变 1 个元素的情况下,该数组能否变成一个非递减数列。 我们是这样定义一个非递减数列的: 对于数组中所有的 i (0 <= i <= n-2),总满足 nums[i] <= nums[i + 1]。 示

额外说明

08.Ubuntu文件权限管理

一、Ubuntu/Linux文件权限 文件权限是指不同的用户或用户组对某个文件拥有的权限,文件的权限分为三种: r:读 w:写 x:可执行。 文件描述形式如下: -rw-rw-r—就是文件权限,第一位表示文件类型,剩下的每三位表示一组权限。分别对应拥有者

额外说明

Spring 事务管理方案和事务管理器及事务控制的API

目录 一、事务管理方案 1. 修改业务层代码 2. 测试 二、事务管理器 1. 简介 2. 在配置文件中引入约束 3. 进行事务配置 三、事务控制的API 1. PlatformTransactionManager接口 2. TransactionDef

额外说明

【Unity3D日常开发】获取天气信息以及地方位置

推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 QQ群:1040082875 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 前段时间有小伙伴问到如何

额外说明

SpringSecurity - 用户动态授权 及 动态角色权限

一、SpringSecurity 动态授权 上篇文章我们介绍了SpringSecurity的动态认证,上篇文章就说了SpringSecurity 的两大主要功能就是认证和授权,既然认证以及学习了,那本篇文章一起学习了SpringSecurity 的动态授

额外说明

InfluxData【付诸实践 02】SpringBoot 集成时序数据库 InfluxDB 应用分享(InfluxDB实例+Feign接口调用InfluxDB API)源码分享

1.InfluxDB实例 1.1 依赖及配置 <dependency> <groupId>org.influxdb</groupId> <artifactId>influxdb-java</artifactId> <version>2.15</ve

额外说明

C语言百日练习测试第八天

前言 今天是刷题第8天,放弃不难,但坚持一定很酷~ 快来跟我一起刷题吧。 第八天写题目录 前言 71.打印7层杨辉三角形72. 重新排列数组73. 冒泡排序74.将数字变为0的操作次数75.四叶玫瑰的数量 71.打印7层杨辉三角形 打印7层杨辉三角形

额外说明

Netty简介和简单的客户端/服务器示例代码

什么是内蒂? Netty是一个NIO客户端-服务器框架,支持快速轻松地开发协议服务器和客户端等网络应用程序。它极大地简化和简化了像TCP和UDP套接字服务器这样的网络编程。 “快速而简单”并不意味着最终的应用程序将遭受可维护性或性能问题。 Netty 是

ads via 小工具