深入理解CAS算法原理

2023-10-31

转载自 深入理解CAS算法原理
https://mp.weixin.qq.com/s?__biz=MzI3ODcxMzQzMw==&mid=2247483728&idx=1&sn=3d734dc972a244891406cfbc443eabed&chksm=eb538466dc240d7033b889665b579a490266b8c8f1e7a08da35f67ca484dad19503e8b230e05&scene=21#wechat_redirect

1、什么是CAS?

CAS:Compare and Swap,即比较再交换。

jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是是悲观锁。

2、CAS算法理解

对CAS的理解,CAS是一种无锁算法,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

CAS比较与交换的伪代码可以表示为:

do{
备份旧数据;
基于旧数据构造新数据;
}while(!CAS( 内存地址,备份的旧数据,新数据 ))

在这里插入图片描述
注:t1,t2线程是同时更新同一变量56的值

    因为t1和t2线程都同时去访问同一变量56,所以他们会把主内存的值完全拷贝一份到自己的工作内存空间,所以t1和t2线程的预期值都为56。

假设t1在与t2线程竞争中线程t1能去更新变量的值,而其他线程都失败。(失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次发起尝试)。t1线程去更新变量值改为57,然后写到内存中。此时对于t2来说,内存值变为了57,与预期值56不一致,就操作失败了(想改的值不再是原来的值)。

(上图通俗的解释是:CPU去更新一个值,但如果想改的值不再是原来的值,操作就失败,因为很明显,有其它操作先改变了这个值。)

    就是指当两者进行比较时,如果相等,则证明共享数据没有被修改,替换成新值,然后继续往下运行;如果不相等,说明共享数据已经被修改,放弃已经所做的操作,然后重新执行刚才的操作。容易看出 CAS 操作是基于共享数据不会被修改的假设,采用了类似于数据库的commit-retry 的模式。当同步冲突出现的机会很少时,这种假设能带来较大的性能提升。

3、CAS开销

前面说过了,CAS(比较并交换)是CPU指令级的操作,只有一步原子操作,所以非常快。而且CAS避免了请求操作系统来裁定锁的问题,不用麻烦操作系统,直接在CPU内部就搞定了。但CAS就没有开销了吗?不!有cache miss的情况。这个问题比较复杂,首先需要了解CPU的硬件体系结构:

在这里插入图片描述

上图可以看到一个8核CPU计算机系统,每个CPU有cache(CPU内部的高速缓存,寄存器),管芯内还带有一个互联模块,使管芯内的两个核可以互相通信。在图中央的系统互联模块可以让四个管芯相互通信,并且将管芯与主存连接起来。数据以“缓存线”为单位在系统中传输,“缓存线”对应于内存中一个 2 的幂大小的字节块,大小通常为 32 到 256 字节之间。当 CPU 从内存中读取一个变量到它的寄存器中时,必须首先将包含了该变量的缓存线读取到 CPU 高速缓存。同样地,CPU 将寄存器中的一个值存储到内存时,不仅必须将包含了该值的缓存线读到 CPU 高速缓存,还必须确保没有其他 CPU 拥有该缓存线的拷贝。

比如,如果 CPU0 在对一个变量执行“比较并交换”(CAS)操作,而该变量所在的缓存线在 CPU7 的高速缓存中,就会发生以下经过简化的事件序列:

CPU0 检查本地高速缓存,没有找到缓存线。

请求被转发到 CPU0 和 CPU1 的互联模块,检查 CPU1 的本地高速缓存,没有找到缓存线。

请求被转发到系统互联模块,检查其他三个管芯,得知缓存线被 CPU6和 CPU7 所在的管芯持有。

请求被转发到 CPU6 和 CPU7 的互联模块,检查这两个 CPU 的高速缓存,在 CPU7 的高速缓存中找到缓存线。

CPU7 将缓存线发送给所属的互联模块,并且刷新自己高速缓存中的缓存线。

CPU6 和 CPU7 的互联模块将缓存线发送给系统互联模块。

系统互联模块将缓存线发送给 CPU0 和 CPU1 的互联模块。

CPU0 和 CPU1 的互联模块将缓存线发送给 CPU0 的高速缓存。

CPU0 现在可以对高速缓存中的变量执行 CAS 操作了

以上是刷新不同CPU缓存的开销。最好情况下的 CAS 操作消耗大概 40 纳秒,超过 60 个时钟周期。这里的“最好情况”是指对某一个变量执行 CAS 操作的 CPU 正好是最后一个操作该变量的CPU,所以对应的缓存线已经在 CPU 的高速缓存中了,类似地,最好情况下的锁操作(一个“round trip 对”包括获取锁和随后的释放锁)消耗超过 60 纳秒,超过 100 个时钟周期。这里的“最好情况”意味着用于表示锁的数据结构已经在获取和释放锁的 CPU 所属的高速缓存中了。锁操作比 CAS 操作更加耗时,是因深入理解并行编程
为锁操作的数据结构中需要两个原子操作。缓存未命中消耗大概 140 纳秒,超过 200 个时钟周期。需要在存储新值时查询变量的旧值的 CAS 操作,消耗大概 300 纳秒,超过 500 个时钟周期。想想这个,在执行一次 CAS 操作的时间里,CPU 可以执行 500 条普通指令。这表明了细粒度锁的局限性。

以下是cache miss cas 和lock的性能对比:

在这里插入图片描述

4、CAS算法在JDK中的应用

在原子类变量中,如java.util.concurrent.atomic中的AtomicXXX,都使用了这些底层的JVM支持为数字类型的引用类型提供一种高效的CAS操作,而在java.util.concurrent中的大多数类在实现时都直接或间接的使用了这些原子变量类。

Java 1.7中AtomicInteger.incrementAndGet()的实现源码为:

在这里插入图片描述
在这里插入图片描述

由此可见,AtomicInteger.incrementAndGet的实现用了乐观锁技术,调用了类sun.misc.Unsafe库里面的 CAS算法,用CPU指令来实现无锁自增。所以,AtomicInteger.incrementAndGet的自增比用synchronized的锁效率倍增。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入理解CAS算法原理 的相关文章

  • HTTP 状态 404 - 请求的资源不可用

    在使用 MyEclipse IDE 中的 Tomcat 服务器和 Struts 2 框架时 我遇到了反复出现的问题 我将我的程序作为服务器应用程序运行 当它运行时 默认的index jsp 文件将成功打开 但应用程序的其他过去都不起作用 当
  • 将链接对象转换为流或集合

    我想迭代堆栈跟踪 堆栈跟踪由可抛出对象组成 其 getCause 返回下一个可抛出对象 最后一次调用 getCause 返回 null 示例 a gt b gt null 我尝试使用 Stream iterable 这会导致 NullPoi
  • Java 创建浮雕(红/蓝图像)

    我正在编写一个 Java 游戏引擎 http victoryengine org http victoryengine org 并且我一直在尝试生成具有深度的 3D 图像 您可以使用那些红色 蓝色眼镜看到 我正在使用 Java2D 进行图形
  • 无法加载 jar 文件的主类

    我使用 Eclipse IDE 开发了一个应用程序 创建应用程序后 我以 jar 格式导出项目 当我尝试运行此 jar 文件时 出现错误 无法加载主类 请帮忙 当您将项目导出为 jar 时 请参阅此所以问题 https stackoverf
  • 有没有好的方法来解析用户代理字符串?

    我有一个Java接收模块User Agent来自最终用户浏览器的字符串的行为需要略有不同 具体取决于浏览器类型 浏览器版本甚至操作系统 例如 FireFox 7 0 Win7 Safari 3 2 iOS9 我明白了User Agent由于
  • 使用 Spring 时实例化对象,用于测试与生产

    使用 Spring 时 应该使用 Spring 配置 xml 来实例化生产对象 并在测试时直接实例化对象 这样的理解是否正确 Eg MyMain java package org world hello import org springf
  • 方法断点可能会大大减慢调试速度

    每当向方法声明行添加断点 在 Intellij IDEA 或 Android Studio 中 时 都会出现一个弹出窗口 方法断点可能会大大减慢调试速度 为什么会这样戏剧性地减慢调试速度 是我的问题吗 将断点放在函数的第一行有什么不同 Th
  • JavaFX - setVisible 隐藏元素但不重新排列相邻节点

    在 JavaFX 中 如果我有一个场景有 2VBox元素和每个VBox有多个Label in it 如果我设置顶部VBox to 无形的 为什么底部VBox 不向上移动顶部的场景VBox was The VBox is 无形的但我希望其他物
  • 如何将 XMP XML 块序列化为现有的 JPEG 图像?

    我有许多 JPEG 图像 其中包含损坏的 XMP XML 块 我可以轻松修复这些块 但我不确定如何将 固定 数据写回图像文件 我目前正在使用 JAVA 但我愿意接受任何能让这项任务变得容易的事情 这是目标关于 XMP XML 的另一个问题
  • 所有junit测试后的清理

    在我的项目中 我必须在所有测试之前进行一些存储库设置 这是使用一些棘手的静态规则来完成的 然而 在所有测试之后我不知道如何进行清理 我不想保留一些神奇的静态数字来引用所有测试方法的数量 我应该一直维护它 最受赞赏的方法是添加一些侦听器 该侦
  • 使用 java 按电子邮件发送日历邀请

    我正在尝试使用 java 发送每封电子邮件的日历邀请 收件人收到电子邮件 但不会显示接受或拒绝的邀请 而是将该事件自动添加到他的日历中 我正在使用 ical4j jar 构建活动 邀请 private Calendar getInvite
  • 参数动态时如何构建 JPQL 查询?

    我想知道是否有一个好的解决方案来构建基于过滤器的 JPQL 查询 我的查询太 富有表现力 我无法使用 Criteria 就像是 query Select from Ent if parameter null query WHERE fiel
  • 从 html 页面和 javascript 调用 java webservice

    我正在尝试从 javascript 调用 java 实现的 Web 服务 使用 NetBeans IDE 我读过很多关于 jQuery 和 AJAX 的内容 但我似乎无法掌握它 假设我的 Web 服务 WSDL 位于 http localh
  • 从 Java 日历迁移到 Joda 日期时间

    以前 当我第一次设计股票应用相关软件时 我决定使用java util Date表示股票的日期 时间信息 后来我体会到了大部分方法java util Date已弃用 因此 很快 我重构了所有代码以利用java util Calendar 然而
  • 如何为 Jackson 编写一个包罗万象的(反)序列化器

    当您提前知道类型时 编写自定义序列化器非常容易 例如 MyType一个人可以写一个MyTypeSerializer extends StdSerializer
  • 如何在keycloak中动态编辑standalone.xml文件

    我正在尝试通过 docker 编辑standalone xml 并尝试添加 但 keycloak 正在使用它standalone xml 但我可以看到standalone xml 文件中的更改 我需要在standalone xml 文件中添
  • 重写Object类的finalize()方法有什么用?

    据我所知 在java中如果我们想手动调用垃圾收集器 我们可以执行System gc 1 我们在重写的finalize 方法中做了哪些操作 2 如果我们想手动调用JVM垃圾收集器 是否需要重写finalize 方法 我们在重写的 Finali
  • Java 编码风格、局部变量与重复方法调用

    我更喜欢使用局部变量而不是多次调用同一方法 I prefer this Vehicle vehicle person getVehicle if vehicle instanceof Car Car car Car vehicle car
  • Java 推断泛型类型

    我正在寻找类似的推断捕获泛型类型的概念 类似于以下方法片段 但不是捕获泛型类型的类 public
  • 使用 eclipse IDE 配置 angularjs

    我想开始使用 AngularJs 和 Java Spring 进行开发 我使用 Eclipse 作为 IDE 我想配置我的 Eclipse 以使这些框架无缝工作 我知道我可能要求太多 但相信我 我已经做了很多研究 你们是我最后的选择 任何帮

随机推荐

  • 尼科彻斯定理

    链接 尼科彻斯定理 牛客题霸 牛客网 nowcoder com 描述 验证尼科彻斯定理 即 任何一个整数m的立方都可以写成m个连续奇数之和 例如 1 3 1 2 3 3 5 3 3 7 9 11 4 3 13 15 17 19 输入一个正整
  • [Machine Learning & Algorithm] 随机森林(Random Forest)

    1 什么是随机森林 作为新兴起的 高度灵活的一种机器学习算法 随机森林 Random Forest 简称RF 拥有广泛的应用前景 从市场营销到医疗保健保险 既可以用来做市场营销模拟的建模 统计客户来源 保留和流失 也可用来预测疾病的风险和病
  • 使用MySQL8.0以上版本和MySQL驱动包8.0以上出现的问题

    目录 1 时区问题 2 驱动程序类问题 1 时区问题 问题代码
  • dll,lib,.a,.so的联系与区别。什么是共享库?与dll的区别是什么?

    dll lib a so的联系与区别 什么是共享库 与dll的区别是什么 区别与联系 静态库与动态库 问题 疑问 什么是共享存档 其他内容 map pdb 文件 区别与联系 本文结合所学和理解进行简单了描述dll与lib a so文件的关系
  • IBatis.net介绍

    从上而下的理解IBatis net这个简易的ORM框架 1 DAL层 public class AccountService public int TestInsertOne Accounts account Object obj Mapp
  • 基于QT开发的截图工具

    概述 这是一个使用QT设计的截图工具 目前效果图 历程 意动 现在网上免费的截图工具很多 最近用了一款很不错的 叫Snipaste 这个软件就是基于QT开发的 不过并没有开源 软件设计的很好用 界面也很清新 于是我也想自己尝试这设计一个这样
  • Oracle 性能最大化

    配置和优化有什么不同 获得最大的性能 配置操作系统 配置Oracle Oracle 性能 调整和配置数据库对象 优化Oracle 最大化 如果你问很多Oracle DBA 你工作中最大的一部分是什么 几乎所有的回答都是 数据库的配置和优化
  • google cartographer参数配置和话题转发

    为了对google cartographer进行实验仿真 安装完成后首先用官方rosbag进行实验没问题后再尝试用自己的rosbag文件 重要的参考资料 https google cartographer ros readthedocs i
  • win10安装TeXLive2019

    下载安装包 到TeX Live官网下载iso安装包 Acquiring TeX Live as an ISO image 点击上图中的链接 会根据网络选择合适的镜像 方便我们下载 我的镜像是上海交通大学的 http mirrors sjtu
  • Pytorch 图像增强 实现翻转裁剪色调等 附代码(全)

    目录 前言 1 裁剪 1 1 中心裁剪 1 2 随机裁剪 1 3 随机尺寸裁剪 2 翻转 2 1 水平翻转 2 2 垂直翻转 2 3 随机旋转 3 色调 3 1 灰度变换 3 2 色彩抖动 3 3 随机翻转颜色 3 4 随机调整锐度 3 5
  • 微信 支付和回调

    1 微信支付 兼容小程序 app h5等方式 RequestMapping value recharge getSign public JSONMessage getSign RequestParam int payType Request
  • Ubuntu 20.04虚拟机开机卡在 /dev/sda* clean ,针对AMD核显的解决办法

    问题描述如标题 此类问题存在的普遍解释是 1 存储空间不足 2 显卡驱动问题 因此在解决问题之前需要先判断自己的问题 首先重启 开机时按Esc建 进入Grub界面 选择第一个选项Ubuntu 之后选择Advanced options for
  • Java中的数据库连接--JDBC

    JDBC Java DataBase Connectivity 即Java数据库连接 就是使用Java语言操作数据库 JDBC的本质 官方定义的定义的一套操作所有关系型数据库的规则 即接口 这边使用MySQL数据库进行测试 1 快速入门 首
  • 非常有趣的的免费API接口,基本上很全了

    一 图灵聊天机器人 http doc tuling123 com openapi2 263611 二 百度地图开放平台 http lbsyun baidu com index php title webapi 三 Eolinker API
  • 【吐血整理】mysql密码正确但无法登陆

    一面 1 二叉搜索树和平衡二叉树有什么关系 强平衡二叉树 AVL 树 和弱平衡二叉树 2 B 树和 B 树的区别 为什么 MySQL 要使用 B 树 3 HashMap 如何解决 Hash 冲突 4 epoll 和 poll 的区别 及其应
  • C++ 语言的单元测试与代码覆盖率

    点击蓝字 关注我们 来源于网络 侵删 前言 测试是软件开发过程中一个必须的环节 测试确保软件的质量符合预期 对于工程师自己来说 单元测试也是提升自信心的一种方式 直接交付没有经过测试的代码是不太好的 因为这很可能会浪费整个团队的时间 在一些
  • Mysql 的安装与配置

    一 windows 服务器下的 mysql 1 安装软件安装 按软件提示一路确定下去 2 压缩包安装 1 解压安装包到自定义路径 2 修改 my ini 配置文件 复制解压好的文件路径 记事本打开 my ini 文件 将basedir 与
  • tie-aware的检索指标

    检索常用指标 P precision R recall F1 AP average precision RR reciprocal rank NDCG normalized discounted cumulative gain ACG av
  • 我对GPIO的的理解

    首先 要先说下GPIO和引脚的区别 整理下网上提出的问题和答案 GPIO的英文全称General Purpose Input Output Ports 中文意思是通用I O端口 在单片机上 单片机有很多管脚 PIN 除了一些特殊的PIN 比
  • 深入理解CAS算法原理

    转载自 深入理解CAS算法原理 https mp weixin qq com s biz MzI3ODcxMzQzMw mid 2247483728 idx 1 sn 3d734dc972a244891406cfbc443eabed chk