21. Java AQS 原理

news2024/9/21 16:16:47

1. 前言

本节内容主要是对 AQS 原理的讲解,之所以需要了解 AQS 原理,是因为后续讲解的 ReentrantLock 是基于 AQS 原理的。本节内容相较于其他小节难度上会大一些,基础薄弱的学习者可以选择性学习本节内容或者跳过本节内容。

  • 了解什么是 AQS,这是认识 AQS 原理的前提,是本节的基础知识点;
  • 了解 AQS 提供的两种锁功能,对其有一个全局的了解;
  • 了解 AQS 的内部框架原理结构,这是本节课程的核心所在,其他所有的知识点讲解都是围绕这一知识点的;
  • 释放锁以及添加线程对于 AQS 内部的变化,这是本节课程的重点知识,了解队列的学习者能够更快的掌握这部分知识;
  • AQS 与 ReentrantLock 的联系,这是本节课程与 ReentrantLock 之间的过度知识。

2. 什么是 AQS

定义:AbstarctQueuedSynchronizer 简称 AQS,是一个用于构建锁和同步容器的框架。

事实上 concurrent 包内许多类都是基于 AQS 构建的,例如 ReentrantLock,ReentrantReadWriteLock,FutureTask 等。AQS 解决了在实现同步容器时大量的细节问题。

AQS 使用一个 FIFO 队列表示排队等待锁的线程,队列头结点称作 “哨兵节点” 或者 “哑结点”,它不与任何线程关联。其他的节点与等待线程关联,每个阶段维护一个等待状态 waitStatus。

3. AQS 提供的两种功能

从使用层面来说,AQS 的锁功能分为两种:独占锁和共享锁。

独占锁:每次只能有一个线程持有锁,比如前面给大家演示的 ReentrantLock 就是以独占方式实现的互斥锁;
共享锁:允许多个线程同时获取锁,并发访问共享资源,比如 ReentrantReadWriteLock。

4. AQS 的内部实现

AQS 的实现依赖内部的同步队列,也就是 FIFO 的双向队列,如果当前线程竞争锁失败,那么 AQS 会把当前线程以及等待状态信息构造成一个 Node 加入到同步队列中,同时再阻塞该线程。当获取锁的线程释放锁以后,会从队列中唤醒一个阻塞的节点 (线程)。

如下图所示,一个节点表示一个线程,它保存着线程的引用(thread)、状态(waitStatus)、前驱节点(prev)、后继节点(next),其实就是个双端双向链表,其数据结构如下:

Tips:AQS 队列内部维护的是一个 FIFO 的双向链表,这种结构的特点是每个数据结构都有两个指针,分别指向直接的后继节点和直接前驱节点。所以双向链表可以从任意一个节点开始,很方便的访问前驱和后继。每个 Node 其实是由线程封装,当线程争抢锁失败后会封装成 Node 加入到 ASQ 队列中去。

5. 添加线程对于 AQS 队列的变化

当出现锁竞争以及释放锁的时候,AQS 同步队列中的节点会发生变化,首先看一下添加线程的场景。

这里会涉及到两个变化

  • 队列操作的变化:新的线程封装成 Node 节点追加到同步队列中,设置 prev 节点以及修改当前节点的前置节点的 next 节点指向自己;
  • tail 指向变化:通过同步器将 tail 重新指向新的尾部节点。

6. 释放锁移除节点对于 AQS 队列的变化

第一个 head 节点表示获取锁成功的节点,当头结点在释放同步状态时,会唤醒后继节点,如果后继节点获得锁成功,会把自己设置为头结点,节点的变化过程如下:

这个过程也是涉及到两个变化:

head 节点指向:修改 head 节点指向下一个获得锁的节点;
新的获得锁的节点:如图所示,第二个节点被 head 指向了,此时将 prev 的指针指向 null,因为它自己本身就是第一个首节点,所以 pre 指向 null。

7. AQS 与 ReentrantLock 的联系

ReentrantLock 实现:ReentrantLock 是根据 AQS 实现的独占锁,提供了两个构造方法如下:

 public ReentrantLock() {
        sync = new NonfairSync();
    }
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

ReentrantLock 有三个内部类:Sync,NonfairSync,FairSync,继承关系如下:

总结:我们可以看到,这三个内部类都是基于 AQS 进行的实现,由此可见,ReentrantLock 是基于 AQS 进行的实现。

ReentrantLock 提供两种类型的锁:公平锁,非公平锁。分别对应 FairSync,NonfairSync。默认实现是 NonFairSync。

8. 小结

本节内容为 AQS 原理进行讲解,会涉及到一些原理问题,队列问题,基础薄弱的学习者可以跳过或者选看本节内容,不会影响后续课程的学习。本节内容其实主要为了提供原理性的知识,对本节的知识掌握,使我们不仅仅是一个使用者。

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

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

相关文章

【目录】阅读须知!全博文、专栏大纲

首先要和大家说一下,博主的文章并不是想到哪里写到哪里,而是以整个大后端为主题,成体系的在写专栏,从和后端紧相关的计算机核心课程开始、到JAVA SE、JAVA EE、到数据库、MQ等各类中间件、再到业务场景、性能优化。当然也会涉及一…

Git秘籍大公开:从基础概念到高级技巧的全面解析

文章目录 前言一、Git基础介绍1. 作用2. 为什么要进行源代码管理?3. Git的诞生4. Git管理源代码特点5. Git操作流程图解 二、工作区暂存区和仓库区介绍1. 工作区2. 暂存区3. 仓库区 三、Git单人本地仓库操作1. 安装git2. 查看git安装结果3. 创建项目4. 创建本地仓库5. 配置个人…

鸿蒙系统:未来智能生态的引领者

在当今这个日新月异的互联网领域,操作系统作为连接硬件与软件的桥梁,其重要性不言而喻。随着华为鸿蒙系统(HarmonyOS)的崛起,一场关于操作系统未来的讨论再次被推向高潮。 鸿蒙OS,华为的全新力作&#xff…

字节码编程javassist之打印方法耗时和入参

写在前面 本文看下如何实现打印方法耗时和入参。 1:程序 需要增强的类: public class ApiTest1 {public Integer strToInt(String str01, String str02) {return Integer.parseInt(str01);}}插桩类 package com.dahuyou.javassist.huohuo.aa;import…

【数据结构】线性表----栈详解

栈 栈(Stack)是一种常见的数据结构,它具有**后进先出(Last In, First Out, LIFO)**的特点。栈的运作类似于物理世界中的叠盘子:最新放上去的盘子最先被拿走,而最底部的盘子最后才能被取出。 如…

C语言学习记录Day2

for循环 for(表达式1;表达式2;表达式3) 循环语句; 注:表达式1:初始化部分.表达式2:条件判断部分 表达式3:调整部分 不可再for循环体内修改循环变量,防止f…

【5G VoNR】VoNR流程简述

博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 本人就职于国际知名终端厂商,负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G技术研究。 博客内容主要围绕…

支持向量机 (support vector machine,SVM)

支持向量机 (support vector machine,SVM) flyfish 支持向量机是一种用于分类和回归的机器学习模型。在分类任务中,SVM试图找到一个最佳的分隔超平面,使得不同类别的数据点在空间中被尽可能宽的间隔分开。 超平面方…

const 修饰不同内容区分

1.修饰局部变量 const int a 1;int const a 1; 这两种是一样的 注意: const int b; 该情况下编译器会报错:常量变量"b”需要初始值设定项 将一个变量没有赋初始值直接const修饰后,在以后时无法更改内容的。 2.修饰常量字符串 a.…

Python前沿技术:机器学习与人工智能

Python前沿技术:机器学习与人工智能 一、引言 随着科技的飞速发展,机器学习和人工智能(AI)已经成为了计算机科学领域的热门话题。Python作为一门易学易用且功能强大的编程语言,已经成为了这两个领域的首选语言之一。本…

U盘管理软件有哪些?3款好用的软件亲测有效!

在数字化办公与数据交换日益频繁的今天,U盘作为便携的存储设备,其重要性不言而喻。 然而,U盘的使用也带来了数据泄露、病毒感染等安全隐患。为了有效管理U盘,确保数据安全与合规性,市场上涌现出了众多U盘管理软件。 小…

电脑选购全解析!你需要知道的一切!

在选择电脑类型时,你可以考虑以下因素: 你的主要用途是什么? 你是否需要携带电脑? 你的预算是多少? 你对性能和图形要求有多高? 你是否需要特定的软硬件功能?根据这些因素,你可以…

生成式人工智能:开发者的得力助手还是职业威胁?

在过去的几年里,生成式人工智能(AIGC)在软件开发领域引发了广泛关注。AI工具在代码生成、错误检测、自动化测试等方面的应用,正在迅速改变开发者的工作方式。AI究竟是在帮助开发者提高效率,还是在逐渐取代他们&#xf…

预提待摊费用处理费时费力?这样做更高效!

一笔费用发生之后,发票取得时间、资金支付时间、费用所属时间都可能不一致,在权责记账规则下,“预提”、“待摊”的账务处理方法成为企业财务业务处理的常用手段。相应地,预提和摊销业务在企业极为常见,仅针对企业规模…

Android network - NUD检测机制(Android 14)

Android network - NUD检测机制 1. 前言2. 源码分析2.1 ClientModeImpl2.2 IpClient2.3 IpReachabilityMonitor 1. 前言 在Android系统中,NUD(Neighbor Unreachable Detection)指的是网络中的邻居不可达检测机制,它用于检测设备是…

雅特力AT32F423开启FPU跟不开启FPU性能差异

在大多数Cortex-M的处理器中调试端口包含一个32位的自由运行计数器,它可以计算 CPU 的时钟周期。计数器是 Debug 观察和跟踪(DWT)模块的一部分,可以很容易地用于测量代码的执行时间。下面的代码是启用和初始化这个特性非常有用。 注意测试需要重新断电上…

浅谈信息技术高效课堂管理:策略、技巧与实践

引言: 在信息化教育的浪潮中,信息技术课程正逐渐成为学校教育体系中的重要组成部分。然而,信息技术课堂的特殊性——高互动性、高度依赖电子设备,给课堂管理带来了前所未有的挑战。如何在保证教学效率的同时,维护良好…

钡铼技术低成本解决方案:注塑机OPC UA接入的智慧选择

在工业4.0与“中国制造2025”战略的引领下,传统注塑机行业正面临前所未有的转型升级挑战。为了在这场技术革新浪潮中保持竞争力,积极接纳并实施OPC UA标准已成为必然趋势。那么,对于传统注塑机而言,如何平滑过渡实现对OPC UA的支持…

C++入门(C语言过渡)

文章目录 前言一、C关键字二、命名空间三、C输入&输出四、缺省参数五、函数重载六、引用七、inline八、nullptr总结 前言 C是一种通用的、高级的、静态类型的编程语言,它在20世纪80年代由丹尼斯里奇创建的C语言基础上发展而来。以下是C发展的一些重要里程碑。 1…

Linux 常见命令使用(超详细版)

文章目录 基本echo关机、重启命令上传下载工具rz/sz<、>、>>ls管道clearcdpwd 文件处理类命令mkdirrmdirtouchcpmv 文件查看类命令catmorelessheadtail 用户管理命令useraddpasswdusermoduserdelgroupaddgroupdel 文件属性类命令chmodchownchgrpln 文件压缩类命令t…