当前位置: 首页 > news >正文

深入理解AQS

  1. 概念

设计初衷:该类利用 状态+队列 实现了一个同步器,更多的是提供一些模板方法(子类必须重写,不然会抛错)。
设计功能:独占、共享模式
  1. 两个核心,state、Queue

2.1 state

setState、compareAndSetState都是用于修改同步状态。看类名其实就知道一个是线程不安全的(setState),一个是使用了乐观锁来保证线程安全(compareAndSetState)。

  • 使用场景

  • setState:应用于释放资源的线程,因为同一时间只有一个使用这个线程不安全的方法去修改state的值,所以不会发生并发安全问题

  • compareAndSetState:应用于尝试获取同步器的资源,由于同一时间可能存在多个资源竞争锁,所以需要使用unsfte类的cas保证线程安全

private volatile int state; // 同步状态值,0:空闲,>0:有多少个线程在同步队列中等待
protected final int getState() { // 获取同步状态return state;
}
protected final void setState(int newState) { // 修改同步状态state = newState;
}
protected final boolean compareAndSetState(int expect, int update) {return unsafe.compareAndSwapInt(this, stateOffset, expect, update); // 通过unsafe类的cas修改同步状态
}

2.2 Queue

底层:带头、尾节点的双向链表
private transient volatile Node head; // 头节点
private transient volatile Node tail; // 尾节点
static final class Node {volatile Node prev; // 前一个节点volatile Node next; // 后一个节点
}
  1. 核心获取同步锁流程

3.1 acquire

public final void acquire(int arg) {// 尝试获取资源失败,且成功加入同步队列,则阻塞线程if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); // 获取不到资源或者加入队列失败,那就中断该线程
}

3.2 tryAcquire

protected boolean tryAcquire(int arg) {throw new UnsupportedOperationException(); // 模板方法,让子类实现
}

3.3 addWaiter

private Node addWaiter(Node mode) {Node node = new Node(Thread.currentThread(), mode); // 转化为同步节点(队列节点类型)// 尾插法Node pred = tail; // 指向尾节点if (pred != null) {node.prev = pred; // 新节点的前一个节点指向尾节点if (compareAndSetTail(pred, node)) { // 因为同时间内有多个线程进入队列,所以使用cas置换尾节点pred.next = node; // 原尾节点的下一个指针指向新插入的节点return node;}}enq(node); // 队列为空,需要初始化队列插入return node;
}

3.4 enq

private Node enq(final Node node) {for (;;) { // 自旋,创建到成功为止Node t = tail;if (t == null) { // 还是并发安全问题,保守判断一下,是不是有人抢先一步if (compareAndSetHead(new Node()))tail = head;} else {node.prev = t; // 插入节点指向尾巴if (compareAndSetTail(t, node)) { // 交换尾节点t.next = node; // 上一个节点指向当前插入节点return t; }}}
}

3.5 acquireQueued

final boolean acquireQueued(final Node node, int arg) {boolean failed = true;try {boolean interrupted = false;for (;;) {final Node p = node.predecessor(); // 获取上一个节点if (p == head && tryAcquire(arg)) { // 检查一下上一个节点是不是头节点,是的话尝试获取资源setHead(node); // 设置头节点为当前节点p.next = null; // GC掉,因为当前节点获取到资源,说明上一个节点已经执行完毕业务了failed = false; // 设置成功return interrupted; // 不阻塞}if (shouldParkAfterFailedAcquire(p, node) && // 没有获取到资源,把线程挂起,别浪费资源parkAndCheckInterrupt())interrupted = true;}} finally {if (failed)cancelAcquire(node); // 获取到资源,取消尝试获取资源}
}

3.6 shouldParkAfterFailedAcquire

private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {int ws = pred.waitStatus; // 上一个节点的wait状态if (ws == Node.SIGNAL) // 上一个节点是SIGNAL状态,说明可以阻塞,回去等通知就行return true;if (ws > 0) { // 如果大于0,说明是CANCELLED状态,那就把前面那些废物节点扔掉do {node.prev = pred = pred.prev;  } while (pred.waitStatus > 0); // 扔啊扔,扔到前一个节点不是废物节点pred.next = node;} else {compareAndSetWaitStatus(pred, ws, Node.SIGNAL); // 小于0,说明前面有节点,更改成SIGNAL状态}return false;
}

3.6.1 waitStatus

static final int CANCELLED =  1; // 废弃状态,有些加入了又不想等,就玩儿
static final int SIGNAL    = -1; // 等待激活下一个节点的状态,下一个节点肯定是被Condiction.await()
static final int CONDITION = -2; // 条件状态,中间节点
static final int PROPAGATE = -3; // 共享模式下的节点状态

3.7 parkAndCheckInterrupt

private final boolean parkAndCheckInterrupt() {LockSupport.park(this); // 挂起当前线程return Thread.interrupted();
}

3.7.1 interrupted

public static boolean interrupted() {return currentThread().isInterrupted(true); // 获取当前线程是否为中断状态
}
private native boolean isInterrupted(boolean ClearInterrupted); // 清除中断标志
  1. 获取同步锁流程图

相关文章:

深入理解AQS

概念设计初衷:该类利用 状态队列 实现了一个同步器,更多的是提供一些模板方法(子类必须重写,不然会抛错)。 设计功能:独占、共享模式两个核心,state、Queue2.1 statesetState、compareAndSetSta…...

JVM学习笔记十:执行引擎

0. 前言 声明: 感谢尚硅谷宋红康老师的讲授。 感谢广大网友共享的笔记内容。 B站:https://www.bilibili.com/video/BV1PJ411n7xZ 本文的内容基本来源于宋老师的课件,其中有一些其他同学共享的内容,也有一些自己的理解内容。 1. …...

【2023-03-10】JS逆向之美团滑块

提示:文章仅供参考,禁止用于非法途径 前言 目标网站:aHR0cHM6Ly9wYXNzcG9ydC5tZWl0dWFuLmNvbS9hY2NvdW50L3VuaXRpdmVsb2dpbg 页面分析 接口流程 1.https://passport.meituan.com/account/unitivelogin主页接口:需获取下面的参数&#xff0…...

全志V853芯片放开快启方案打印及在快起方式下配置isp led的方法

全志V85x芯片 如何放开快启方案的打印? 1.主题 如何放开快启方案的打印 2.问题背景 产品:v851系列快启方案 软件:tina 其他:特有版本信息添加自由描述 (如固件版本,复现概率,特定环境&#x…...

大数据 | (一)Hadoop伪分布式安装

大数据原理与应用教材链接:大数据技术原理与应用电子课件-林子雨编著 Hadoop伪分布式安装借鉴文章:Hadoop伪分布式安装-比课本详细 大数据 | (二)SSH连接报错Permission denied:SSH连接报错Permission denied 哈喽&a…...

Django/Vue实现在线考试系统-06-开发环境搭建-Django安装

1.0 基本介绍 Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架。 使用 Django,只要很少的代码,Python 的程序开发人员就可以轻松地完成一个正式网站所需要的大部分内容,并进一步开发出全功能的 Web 服务 Django 本身基于 MVC 模型,即 Model(模型)+ View(…...

KaiwuDB 时序引擎数据存储内存对齐技术解读

一、理论1、什么是内存对齐现代计算机中内存空间都是按照 byte 划分的,在计算机中访问一个变量需要访问它的内存地址,从理论上看,似乎对任何类型的变量的访问都可以从任何地址开始。但在实际情况中,通常在特定的内存地址才能访问特…...

IR 808 Alkyne,IR-808 alkyne,IR 808炔烃,近红外吲哚类花菁染料

【产品理化指标】:中文名:IR-808炔烃英文名:IR-808 alkyne,Alkyne 808-IR CAS号:N/AIR-808结构式:规格包装:10mg,25mg,50mg,接受各种复杂PEGS定制服务&#x…...

elasticsearch

这里写目录标题1.初识ElasticSearch1.1 了解ES1.2 倒排索引1.2.1 正向索引1.2.2 倒排索引1.2.3 正向和倒排1.3 ES的一些概念1.3.1 文档和字段1.3.2 索引和映射1.3.3 mysql和elasticsearch1.4 安装ES、kibana1.初识ElasticSearch 1.1 了解ES elasticsearch是一款非常强大的开源…...

并发编程---java锁

java锁一 多线程锁synchronized案例分析1.1synchronized介绍1.2 synchronized案例分析1.2.1.标准访问,请问先打印邮件还是短信?1.2.2.邮件⽅法暂停4秒钟,请问先打印邮件还是短信?分析1.2.3.新增⼀个普通⽅法hello(&…...

品牌营销 | 学习如何最大限度地发挥品牌营销的作用

您是否想过如何最大限度地发挥品牌营销的潜力?这是一项艰巨的挑战,通过了解品牌营销的基本组成部分,您可以成功地推广您的品牌。 (图源:Pixabay) 品牌营销的基本组成部分 你需要做什么来发展稳固的品牌&am…...

Linux驱动的同步阻塞和同步非阻塞

在字符设备驱动中,若要求应用与驱动同步,则在驱动程序中可以根据情况实现为阻塞或非阻塞一、同步阻塞这种操作会阻塞应用程序直到设备完成read/write操作或者返回一个错误码。在应用程序阻塞这段时间,程序所代表的进程并不消耗CPU的时间&…...

LearnOpenGL-光照-5.投光物

本人刚学OpenGL不久且自学,文中定有代码、术语等错误,欢迎指正 我写的项目地址:https://github.com/liujianjie/LearnOpenGLProject 文章目录投光物平行光点光源聚光不平滑的例子平滑例子投光物 前面几节使用的光照都来自于空间中的一个点 即…...

【C语言】每日刷题 —— 牛客语法篇(1)

前言 大家好,今天带来一篇新的专栏c_牛客,不出意外的话每天更新十道题,难度也是从易到难,自己复习的同时也希望能帮助到大家,题目答案会根据我所学到的知识提供最优解。 🏡个人主页:悲伤的猪大…...

【深度学习】Subword Tokenization算法

在自然语言处理中,面临的首要问题是如何让模型认识我们的文本信息,词,是自然语言处理中基本单位,神经网络模型的训练和预测都需要借助词表来对句子进行表示。 1.构建词表的传统方法 在字词模型问世之前,做自然语言处理…...

五分钟了解支付、交易、清算、银行等专业名词的含义?

五分钟了解支付、交易、清算、银行等专业名词的含义?1. 支付类名词01 支付应用02 支付场景03 交易类型04 支付类型(按通道类型)05 支付类型(按业务双方类型)06 支付方式07 支付产品08 收银台类型09 支付通道10 通道类型…...

4个工具,让 ChatGPT 如虎添翼!

LightGBM中文文档 机器学习统计学,476页 机器学习圣经PRML中文版...

初识PO、VO、DAO、BO、DTO、POJO时

PO、VO、DAO、BO、DTO、POJO 区别分层领域模型规约DO(Data Object)DTO(Data Transfer Object)BO(Business Object)AO(ApplicationObject)VO(View Object)Query领域模型命名规约:一、PO :(persistant object ),持久对象二、VO :(value object) &#xff0…...

[2.2.4]进程管理——FCFS、SJF、HRRN调度算法

文章目录第二章 进程管理FCFS、SJF、HRRN调度算法(一)先来先服务(FCFS, First Come First Serve)(二)短作业优先(SJF, Shortest Job First)对FCFS和SJF两种算法的思考(三…...

【代码随想录Day55】动态规划

583 两个字符串的删除操作 https://leetcode.cn/problems/delete-operation-for-two-strings/72 编辑距离https://leetcode.cn/problems/edit-distance/...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

基础测试工具使用经验

背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...

RabbitMQ 各类交换机

为什么要用交换机? 交换机用来路由消息。如果直发队列,这个消息就被处理消失了,那别的队列也需要这个消息怎么办?那就要用到交换机 交换机类型 1,fanout:广播 特点 广播所有消息​​:将消息…...

十二、【ESP32全栈开发指南: IDF开发环境下cJSON使用】

一、JSON简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,具有以下核心特性: 完全独立于编程语言的文本格式易于人阅读和编写易于机器解析和生成基于ECMAScript标准子集 1.1 JSON语法规则 {"name"…...