【JavaEE】CAS -- 多线程篇(7)

CAS

  • 1. 什么是 CAS
  • 2. CAS 伪代码
  • 3. CAS 是怎么实现的
  • 4. CAS的应用
    • 4.1 实现原子类
    • 4.2 实现自旋锁
  • 5. CAS 的 ABA 问题

1. 什么是 CAS

  • CAS: 全称Compare and swap,字面意思:”比较并交换“
  • 能够比较和交换 某个寄存器中的值和内存中的值, 看是否相等, 如果相等, 则把另一个寄存器中的值和内存进行交换

2. CAS 伪代码

  • 下面写的代码不是原子的, 真实的 CAS 是一个原子的硬件指令完成的. 这个伪代码只是辅助理解CAS 的工作流程
boolean CAS(address, expectValue, swapValue) {if (&address == expectedValue) {&address = swapValue;return true;}return false;
}

伪代码解释

  • address 是内存地址, 剩下的两个都是寄存器中的值 – 一个表示旧的数据的值, 一个表示要更新的数据的值
  • 这一段逻辑, 是通过一条 CPU 指令完成的 – 所以这个操作是原子的
  • 解释交换语句只有一条赋值语句的原因: 把 address 内存的值 和 swapValue 寄存器的值进行交换, 但是我们一般重点关注是内内存中的值, 寄存器往往作为保存临时数据的方法, 这里的值是干啥的, 很多时候就忽略了

3. CAS 是怎么实现的

针对不同的操作系统,JVM 用到了不同的 CAS 实现原理,简单来讲:

  • java 的 CAS 利用的的是 unsafe 这个类提供的 CAS 操作;
  • unsafe 的 CAS 依赖了的是 jvm 针对不同的操作系统实现的 Atomic::cmpxchg;
  • Atomic::cmpxchg 的实现使用了汇编的 CAS 操作,并使用 cpu 硬件提供的 lock 机制保证其原子性。

简而言之,是因为硬件予以了支持,软件层面才能做到

4. CAS的应用

4.1 实现原子类

标准库中提供了 java.util.concurrent.atomic 包, 里面的类都是基于这种方式来实现的.
在这里插入图片描述
典型的就是 AtomicInteger 类. 其中的 getAndIncrement 相当于 i++ 操作.

原子类的使用

public static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 5000; i++) {// count++count.getAndIncrement();// ++count// count.incrementAndGet();// count--// count.getAndDecrement();// --count// count.decrementAndGet();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 5000; i++) {// count++count.getAndIncrement();}});t1.start();t2.start();t1.join();t2.join();System.out.println(count.get());
}

伪代码实现

class AtomicInteger {private int value;public int getAndIncrement() {int oldValue = value;while ( CAS(value, oldValue, oldValue+1) != true) {oldValue = value;}return oldValue;}
}

假设两个线程同时调用 getAndIncrement

  1. 两个线程都读取 value 的值到 oldValue 中. (oldValue 是一个局部变量, 在栈上. 每个线程有自己的栈)

在这里插入图片描述

  1. 线程1 先执行 CAS 操作. 由于 oldValue 和 value 的值相同, 直接进行对 value 赋值.
  • 注意:
    • CAS 是直接读写内存的, 而不是操作寄存器.
    • CAS 的读内存, 比较, 写内存操作是一条硬件指令, 是原子的.

在这里插入图片描述

  1. 线程2 再执行 CAS 操作, 第一次 CAS 的时候发现 oldValue 和 value 不相等, 不能进行赋值. 因此需要进入循环;
    在循环里重新读取 value 的值赋给 oldValue

在这里插入图片描述

  1. 线程2 接下来第二次执行 CAS, 此时 oldValue 和 value 相同, 于是直接执行赋值操作.
    在这里插入图片描述
  2. 线程1 和 线程2 返回各自的 oldValue 的值即可.

通过形如上述代码就可以实现一个原子类. 不需要使用重量级锁, 就可以高效的完成多线程的自增操作.

本来 check and set 这样的操作在代码角度不是原子的. 但是在硬件层面上可以让一条指令完成这个操作, 也就变成原子的了.

4.2 实现自旋锁

基于 CAS 实现更灵活的锁, 获取到更多的控制权.

自旋锁伪代码

public class SpinLock {private Thread owner = null;public void lock(){// 通过 CAS 看当前锁是否被某个线程持有. // 如果这个锁已经被别的线程持有, 那么就自旋等待. // 如果这个锁没有被别的线程持有, 那么就把 owner 设为当前尝试加锁的线程. while(!CAS(this.owner, null, Thread.currentThread())){}}public void unlock (){this.owner = null;}
}

伪代码分析

在这里插入图片描述

5. CAS 的 ABA 问题

  • CAS 关键要点, 是比较 寄存器1 和 内存的值, 通过这里的是否相等来判定 内存的值 是否发生了该变;

    • 如果内存的值变量, 存在其他线程进行了修改;
    • 如果内存的值没有改变, 没有别的线程修改, 接下来的修改就是安全的
  • 问题提出: 这里的值没有变, 就一定没有别的线程修改吗?

    • 答案是否定的!

    • 内存的值变化过程可能是 A -> B -> A在这里插入图片描述

    • 这就是是所谓的ABA问题

  • 大部分情况下, 就算是出现 ABA 问题, 也没啥太大影响, 但是如果与发哦一些极端的场景, 就不一定了

ABA 问题引出的 bug

在这里插入图片描述

解决方案

  • 给要修改的值, 引入版本号. 在 CAS 比较数据当前值和旧值的同时, 也要比较版本号是否符合预期.
    • CAS 操作在读取旧值的同时, 也要读取版本号.
    • 真正修改的时候,
      • 如果当前版本号和读到的版本号相同, 则修改数据, 并把版本号 + 1
      • 如果当前版本号高于读到的版本号. 就操作失败(认为数据已经被修改过了).

在这里插入图片描述

在 Java 标准库中提供了 AtomicStampedReference 类. 这个类可以对某个类进行包装, 在内部就提供了上面描述的版本管理功能.

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

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

相关文章

[support2022@cock.li].faust、[tsai.shen@mailfence.com].faust勒索病毒数据怎么处理|数据解密恢复

引言&#xff1a; 威胁网络安全的恶意软件不断涌现&#xff0c;而[support2022cock.li].faust勒索病毒则是其中的一员。这个网络黑暗角落的新星&#xff0c;以其数据绑架的方式&#xff0c;一度成为数据安全的威胁焦点。本文将探究[support2022cock.li].faust勒索病毒的运作方…

全是干货!2023年双十一买什么最划算、双十一值得买的好物推荐

在双十一前选购到好物&#xff0c;打败99.99%的人&#xff01;看了下日历马上就要到一年一度的购物节了&#xff0c;双十一都想好买什么了吗朋友们&#xff1f;双十一购物狂欢即将来临&#xff0c;你是否已经开始准备购买自己心仪的商品&#xff1f;在这个购物狂欢节中&#xf…

华为ERP,包含哪些内容?技术的先进性体现在哪里?

华为作为全球领先的信息和通信技术&#xff08;ICT&#xff09;解决方案提供商&#xff0c;其企业资源规划&#xff08;ERP&#xff09;系统是一个高度复杂且集成的管理软件平台&#xff0c;用于优化公司内部的业务流程和资源分配。华为ERP系统包括一系列模块和功能&#xff0c…

【Jenkins 安装】

一&#xff1a;安装文件夹准备 在/home/admin 界面下新建三个文件夹&#xff0c;用来安装tomcat、maven 1.打开&#xff0c;/home/admin目录 cd /home/admin 2.新建三个文件夹 mkdir tomcat mkdir maven 二&#xff1a;安装tomcat 1.打开tomcat目录进行tomcat的安装 访问:h…

Rocksdb LSM Tree Compaction策略

RocksDB读写简介 直接画图说明。这张图取自Flink PMC大佬Stefan Richter在Flink Forward 2018演讲的PPT&#xff0c;笔者重画了一下。 RocksDB的写缓存&#xff08;即LSM树的最低一级&#xff09;名为memtable&#xff0c;对应HBase的MemStore&#xff1b;读缓存名为block cac…

文生图——DALL-E 3 —论文解读——第一版

概述 本文主要是DALLE 3官方第一版技术报告&#xff08;论文&#xff09;的解读&#xff0c;原文《Improving Image Generation with Better Captions》论文解读。该文要提升文生图的效果&#xff0c;将技术点放到了&#xff0c;提升指令跟随能力上&#xff0c;然后顺藤摸瓜分为…

深眸科技以需求定制AI视觉解决方案,全面赋能产品外观缺陷检测

产品外观是影响产品质量最重要的因素之一&#xff0c;其平整度、有无瑕疵等不仅影响到产品美观&#xff0c;甚至能够直接影响产品本身的使用和后续加工&#xff0c;给企业带来重大经济损失。 随着人工智能技术的快速发展&#xff0c;机器视觉与AI技术的结合应用加速渗透进工业…

国产开发板上打造开源ThingsBoard工业网关--基于米尔芯驰MYD-JD9X开发板

本篇测评由面包板论坛的优秀测评者“JerryZhen”提供。 本文将介绍基于米尔电子MYD-JD9X开发板打造成开源的Thingsboard网关。 Thingsboard网关是一个开源的软件网关&#xff0c;采用python作为开发语言&#xff0c;可以部署在任何支持 python 运行环境的主机上&#xff0c;灵…

vxe-table 打包部署上线,校验样式失效

正常效果 打包上线后的样式 样式失效原因&#xff0c;vue版本与vxe-table版本不兼容导致 版本 "vxe-table": "^4.3.5", "vxe-table-plugin-element": "^3.0.6", "xe-utils": "^3.5.4",由于vxe-table最新版本是4…

【Docker】联合探讨Docker:容器化技术的革命性应用

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 &#x1f4d5;作者简介&#xff1a;热…

【大数据】Hadoop

文章目录 概述Hadoop组成HDFSMapReduce写MapReduce程序&#xff08;Hadoop streaming&#xff09; YARNHadoop 启动 工作方式Hadoop的主从工作方式Hadoop的守护进程 运行模式本地运行模式伪分布式运行模式完全分布式运行模式 Hadoop高可用的解决方案ZooKeeper quorumZKFC 环境搭…

postman接收后端返回的文件流并自动下载

不要点send&#xff0c;点send and download&#xff0c;postman接受完文件流会弹出文件保存框让你选择保存路径

【Sentinel】Sentinel簇点链路的形成

说明 一切节点的跟是 machine-root&#xff0c;同一个资源在不同链路会创建多个DefaultNode&#xff0c;但是在全局只会创建一个 ClusterNode machine-root/\/ \EntranceNode1 EntranceNode2/ \/ \DefaultNode(nodeA) DefaultNode(nodeA)|…

Fast R-CNN(2015.9)

文章目录 AbstractIntroductionR-CNN and SPPnet训练是一个多阶段的流水线训练在空间和时间上都很昂贵目标检测速度慢 Contributions Fast R-CNN architecture and trainingThe RoI pooling layerInitializing from pre-trained networksFine-tuning for detectionMulti-task l…

【ARM Coresight 系列文章 3.3 - ARM Coresight SWD 协议详细介绍】

文章目录 1.1 SWD 协议框图1.2 读/写时序及命令1.2.1 SWD 时序1.2.2 SWD 命令详情1.3 芯片探测1.3.1 获取芯片 ID1.4 读/写操作1.1 SWD 协议框图 SWD协议可以配置SoC内部几乎所有的寄存器。时钟信号由SWCLK 管脚输入,数据信号从SWDIO管脚输入输出。首先 HOST 对SW-DP 进行操作…

OTA: Optimal Transport Assignment for Object Detection 论文和代码学习

OTA 原因步骤什么是最优传输策略标签分配的OT正标签分配负标签分配损失计算中心点距离保持稳定动态k的选取 整体流程代码使用 论文连接&#xff1a; 原因 1、全部按照一个策略如IOU来分配GT和Anchors不能得到全局最优&#xff0c;可能只能得到局部最优。 2、目前提出的ATSS和P…

井盖异动传感器丨井盖状态监测仪助力排水管网系统装上“眼睛”

智慧排水技术作为现代城市管理的重要组成部分&#xff0c;正在以其高效、可持续和环保的特点在全球范围内得到广泛应用。 随着城市化进程的不断加速&#xff0c;城市面临着日益严重的排水管理挑战。国家政府也在《全国城市市政基础设施建设“十三五”规划》等明确要求建设城市…

vue2.x封装svg组件并使用

第一步&#xff1a;安装svg-sprite-loader插件 <!-- svg-sprite-loader svg雪碧图 转换工具 --> <!-- <symbol> 元素中的 path 就是绘制图标的路径&#xff0c;这种一大串的东西我们肯定没办法手动的去处理&#xff0c; 那么就需要用到插件 svg-sprite-loader …

福建三明大型工程机械3D扫描测量工程零件开模加工逆向抄数-CASAIM中科广电

高精度3D扫描测量技术已经在大型工件制造领域发挥着重要作用&#xff0c;可以高精度高效率实现全尺寸三维测量&#xff0c;本期&#xff0c;CASAIM要分享的应用是大型工程机械3D扫描测量案例。 铣轮是深基础施工领域内工法先进、技术复杂程度高、高附加值的地连墙设备&#xff…

基于QT的图书管理系统

获取代码&#xff1a; 知识付费时代&#xff0c;低价有偿获取代码&#xff0c;请理解&#xff01; (1) 下载链接: 后发(2) 添加博主微信获取&#xff08;有偿&#xff09;,备注来源: mryang511688(3) 快速扫码咨询&#xff1a; 项目描述 技术&#xff1a;C、QT等 摘要&#…