当前位置: 首页 > 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/...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

python打卡day49

知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络&#xf…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

Netty自定义协议解析

目录 自定义协议设计 实现消息解码器 实现消息编码器 自定义消息对象 配置ChannelPipeline Netty提供了强大的编解码器抽象基类,这些基类能够帮助开发者快速实现自定义协议的解析。 自定义协议设计 在实现自定义协议解析之前,需要明确协议的具体格式。例如,一个简单的…...

Linux 内存管理调试分析:ftrace、perf、crash 的系统化使用

Linux 内存管理调试分析&#xff1a;ftrace、perf、crash 的系统化使用 Linux 内核内存管理是构成整个内核性能和系统稳定性的基础&#xff0c;但这一子系统结构复杂&#xff0c;常常有设置失败、性能展示不良、OOM 杀进程等问题。要分析这些问题&#xff0c;需要一套工具化、…...

DL00871-基于深度学习YOLOv11的盲人障碍物目标检测含完整数据集

基于深度学习YOLOv11的盲人障碍物目标检测&#xff1a;开启盲人出行新纪元 在全球范围内&#xff0c;盲人及视觉障碍者的出行问题一直是社会关注的重点。尽管技术不断进步&#xff0c;许多城市的无障碍设施依然未能满足盲人出行的实际需求。尤其是在复杂的城市环境中&#xff…...

第6章:Neo4j数据导入与导出

在实际应用中&#xff0c;数据的导入与导出是使用Neo4j的重要环节。无论是初始数据加载、系统迁移还是数据备份&#xff0c;都需要高效可靠的数据传输机制。本章将详细介绍Neo4j中的各种数据导入与导出方法&#xff0c;帮助读者掌握不同场景下的最佳实践。 6.1 数据导入策略 …...