JUC 之 比较交换 CAS

news2024/9/29 18:13:45

—— CAS(Compare And Swap)

没有 CAS 之前,多线程环境下不使用原子类保证线程安全 i++,只能通过 synchronized 加锁的方式,高并发多写情况下,性能影响很大;使用 CAS 之后,可以使用原子类(Atomic )保证线程安全,类似于 乐观锁

基本概念 & 底层原理

原理

  • CAS(compare and swap):比较并交换,是一条 CPU 并发原语,它包含 3 个操作数——内存位置、预期原值、更新值(主内存值、工作内存值、更新值)
    • 执行 CAS 操作的时候,将内存位置的值与预期原值比较;
    • 如果 匹配, 那么处理器会自动将 位置值 更新为 新值
    • 如果 不匹配,处理器不做任何操作,多个贤臣同时执行 CAS 操作 只有一个会成功
    • 当且仅当旧的预期值 和 内存值 相同时,将 内存值 修改为 更新值,否则什么都不做或重来,当它重来重试的这种行为称为 自旋
      在这里插入图片描述

硬件保证

  • CAS 是 JDK 提供的非阻塞原子性操作,它通过 硬件 保证了比较-更新的原子性,它是非阻塞的且自身具有原子性,效率更高,且通过硬件保证,更可靠
  • CAS 是一条 CPU 的原子指令(cmpxchg指令【compare x change】),不会造成所谓的数据不一致问题,Unsafe 提供的 CAS 方法底层实现即为 CPU 指令 cmpxchg
    • 执行cmpxchg指令时,会判断当前系统是否为多核系统,如果是就给总线加锁,只有一个线程会对总线加锁成功,加锁成功之后会执行 CAS 操作,也就是说 CAS的原子性实际上是 CPU 实现独占的,比起用 synchronized 重量级锁,这里的排他时间要短很多,所以在多线程情况下性能会更好

源码说明

    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
  • 参数说明
    • this:表示要操作的对象
    • valueOffset:表示要操作对象中属性地址的偏移量
    • expect:表示需要修改数据的期望的值
    • update:表示需要修改为的新值

Unsafe 类详解

  • 是 CAS 的核心类,由于 Java 方法无法直接访问底层系统,需要通过本地(native)方法来访问,Unsafe 相当于一个后门,基于该类可以直接操作特定内存的数据。Unsafe 类存在于 sun.misc 包中,其内部方法操作可以像 C 的指针一样直接操作内存,因为 Java 中 CAS 操作的执行依赖于 Unsafe 类的方法
  • Unsafe 类中的所有方法都是 native 修饰的,所以 Unsafe 类中的方法都直接调用操作系统底层资源执行相应任务
  • 变量 valueOffset,Unsafe 就是根据内存偏移地址来获取数据的
  • 变量 value 用 volatile 修饰,保证了多线程之间的内存可见性
  • AtomicInteger 类主要利用 CAS + volatile + native 方法来保证原子操作,从而避免 synchronized 的高开销,执行效率大为提升
  • CAS 并发原语体现在 Java 语言中就是 sun.misc.Unsafe 类中的各个方法。调用 Unsafe 类中的 CAS 方法,JVM 会帮我们实现出 CAS 汇编指令。这是一种完全依赖于硬件的功能,通过它实现了原子操作。由于 CAS 是一种系统原语,原语属于操作系统用语范畴,是由若干条指令组成的,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被打断,也就是说 CAS 是一条 CPU 的原子指令,不会造成所谓的数据不一致问题

总结

  • CAS 是靠硬件实现的,从而在硬件层面提升效率,最底层还是交给硬件来保证原子性和可见性
  • 实现方式是基于硬件平台的汇编指令,在 intel 的 CPU 中(X86机器),使用的是汇编指令 cmpxchg 指令
  • 核心思想是:比较要更新变量的值V和预期值E,相等才会将V的值设置为新值 N,如果不相等自旋

缺点

  • 自旋引起的循环时间长,CPU 开销大
  • ABA 问题
    • CAS 算法实现一个重要前提是,需要取出内存中某个时刻的数据并在当下时刻比较并交换,那么在这个时间差会导致数据的变化
    • 比如一个线程A 从内存位置取出 1,另一个线程B 也从内存中取出 1,并且线程 B 进行了一些操作将 1 改为 2,然后线程B 又将 2 改回了 1,这时线程 A 进行CAS 操作发现内存中仍然是 1,预期 OK ,进行操作更改
    • 尽管线程 A 的 CAS 操作成功,但是不代表这个过程就是没有问题的

通过版本号戳记流水原子引用(AtomicStampedReference)可解决 ABA 问题

—— 原子类

基本类型原子类

  • AtomicInteger
  • AtomicBolean
  • AtomicLong

数组类型原子类

  • AtomicIntegerArray
  • AtomicLongArray
  • AtomicReferenceArray

引用类型原子类

AtomicReference

AtomicStampedReference

  • 携带版本号的引用类型原子类,可以解决 ABA 问题
  • 解决修改过几次的问题
  • 版本号流水戳原子引用

AtomicMarkableReference

  • 原子更新带有标记位的引用类型对象
  • 解决是否修改过(就是将版本号简化为 true|false,类似于一次性使用)
  • 状态戳(true、false)原子引用

对象的属性修改原子类

  • AtomicIntegerFieldUpdater
  • AtomicLongFieldUpdater
  • AtomicReferenceFieldUpdater

原子操作增强类

  • DoubleAccumulator
  • DoubleAdder
  • LongAccumulator
  • LongAdder

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

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

相关文章

公司对不同职级能力抽象要求的具体化

要先把当前级别要求的能力提升到精通,然后尝试做下一级别的事情。 但可能不确定高一级的能力要求究竟怎样,不同Title,如“工程师”“高级工程师”和“资深工程师”等。但这样 Title 对我们理解不同级别的能力要求,完全无用。“高…

RecycleView详解

listview缓存请看: listview优化和详解RecycleView 和 ListView对比:使用方法上ListView:继承重写 BaseAdapter,自定义 ViewHolder 与 converView优化。RecyclerView: 继承重写 RecyclerView.Adapter 与 RecyclerView.ViewHolder。设置 Layou…

【华为OD机试模拟题】用 C++ 实现 - 英文输入法(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 分积木(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 吃火锅(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - RSA 加密算法(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 构成的正方形数量(2023.Q1) 【华为OD机试模拟…

计算机组成原理考研题精选

运算 1 D状态寄存器of,cf,sf,zf看结果,数据总线传输数据,Alu是核心器件,地址寄存器是存储器件 2 (74条消息) 【细碎知识1】浮点数的规格化_SinHao22的博客-CSDN博客_浮点数规格化 (74条消息) IEEE754 浮点数:简读案例秒懂_theR…

数据结构之8种排序算法

文章目录1.插入排序2.希尔排序:3.冒泡排序4.快速排序5.简单选择排序6.堆排序在堆中插入新元素:在堆中删除一个元素:7.归并排序8.基数排序9.外部排序排序算法1.插入排序 每次将一个待排序的记录按其关键字大小插入到前面已经排好序的子序列中…

量子态操作:基于门的三态旋转

R-旋转操作 在量子计算中,RX, RY, RZ门是三种基本的单量子比特旋转门,它们分别绕X轴、Y轴、Z轴旋转量子比特的态矢量。 RX旋转门:绕X轴旋转角度为θ\thetaθ的RX门的矩阵表示为: Rx(θ)(cosθ2−isinθ2−isinθ2cosθ2)R_x(\th…

Python3+Selenium3自动化测试

此前对网页内容进行元素定位的操作,接下来就可以对已经定位的元素进行操作了,一般情况下定位好元素后通过IDE的提示就可以了解到有哪些方法 #coding utf-8 import time from selenium import webdriver from selenium.webdriver.common.by import By dr…

JAVA多线程牌号系统开发与应用

技术:Java等摘要:牌号系统是为解决一些服务业营业大厅排队问题而设计的,它能够有效地提高工作人员的工作效率,也能够使顾客合理的安排等待时间,让顾客感到服务的公平公正。论文首先讨论了牌号系统的背景、意义、应用现…

力扣-订单最多的客户

大家好,我是空空star,本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目:586. 订单最多的客户二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.其他总…

算法模板总结(自用)

算法模板总结滑动窗口双指针算法数组相关合并两个有序数组左右指针技巧快慢指针技巧字符串相关左右指针反转字符串问题快慢指针替换空格字符问题链表相关快慢双指针删除链表的倒数第N个节点链表相交环形链表链表操作几数之和两数之和四个数组的四数之和三数之和同一数组中四数之…

(十)守恒律(主平衡原理)

守恒律表示了物体中某些物理场量之间的关系,它可表述为:某一时刻 ttt,对于物理场量 Φ\bold\PhiΦ 在物体体积 vvv 上的物质积分,其时间变化率等于另一物理场量 Ψ\bold\PsiΨ(源) 在该体积上的物质积分,与通过物体表面…

AI高效学习路径总结

最近chatgpt爆红,百度近日也官宣了大模型新项目“文心一言”(英文名ERNIE Bot),即将在今年3月面向公众开放,我先期待一波,到时候给同学们说说感受。 这也不是第一次人工智能引起广泛关注了,随着…

外贸人员如何让远程办公和在办公室一样办公

俗话说:“工欲善其事,必先利其器”。作为外贸人员,常用的工具主要分为三大类:客户管理工具、翻译工具、邮箱工具。往往外贸人员会忽略另一类工具:远程类工具。客户管理工具 有了客户管理工具,企业和员工都可…

软件测试之正交法

正交法 通过分析我们发现,对于图中的程序而言,我们要设计81条测试用例,那么有没有一种方法能够使用最小的测试过程集合获得最大的测试覆盖率呢? 1. 概述 1.1 定义 正交法,也叫正交实验法或者正交排列法, 就是使用最小的测试过程集合获得最大的测试覆盖率。 “正交实验”是…

LINUX应用GUI开发C++ 之gtkmm4(1)

目录概述GTKgtkmm安装gtkmm4hello,worldcodelite配置代码解释概述 GTK GTK是一个小部件工具包。GTK创建的每个用户界面都由小部件组成。这是在C语言中使用GObject实现的,GObject是一个面向对象的C语言框架。窗口小部件是主容器。然后通过向窗口中添加按钮、下拉菜…

Android Studio中创建java工程

1. 前言 电脑环境: Ubuntu 18.04 开发工具环境:Android Studio 4.1.3 版本 经常要使用验证Java API, 把配置环境步骤记录一下 2. 创建步骤 2.1 新建一个Android Studio App工程 New ---> New Project ---> 选择一个Activity主题---> Finish 就创建ok 2.2 …

如何防护DDOS攻击

DDOS攻击的趋势呈现出明显的增长趋势,特别是在网络攻击技术的发展和攻击者的技术水平提高的情况下,DDOS攻击的发生频率和规模也在不断增加。此外,随着网络技术的发展,攻击者也可以利用更多的技术手段来实施DDOS攻击,比…

kali环境搭建

一、渗透为什么要使用kali? 1、系统开源 kali linux实际上是开源的操作系统,其中内置了几百种工具而且是免费的,可以非常方便的为测试提供上手即用的整套工具,而不需要繁琐的搭建环境,及收集工具下载安装等步骤 2、系统…

通过OpenAI来做机械智能故障诊断-测试(1)

通过OpenAI来做机械智能故障诊断 1. 注册使用2. 使用案例1-介绍故障诊断流程2.1 对话内容2.2 对话小结3. 使用案例2-写一段轴承故障诊断的代码3.1 对话内容3.2 对话小结4. 对话加载Paderborn轴承故障数据集并划分4.1 加载轴承故障数据集并划分第一次测试4.2 第二次加载数据集自…

【华为OD机试模拟题】用 C++ 实现 - 挑选字符串(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 货币单位换算(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 选座位(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 停车场最大距离(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 重组字符串(2023.Q1) 【华为OD机试模…