详解CAS(Compare and swap)

一、什么是 CAS

CAS: 全称Compare and swap,字⾯意思:”⽐较并交换“,⼀个 CAS 涉及到以下操作:
我们假设内存中的原数据V,旧的预期值A,需要修改的新值B。
  1. 比较 A 与 V 是否相等。(⽐较)
  2. 如果⽐较相等,将 B 写⼊ V。(交换)
  3. 返回操作是否成功。

CAS 伪代码

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

 两种典型的不是 "原⼦性" 的代码

  1. check and set (if 判定然后设定值) [上⾯的 CAS 伪代码就是这种形式]
  2. read and update (i++) [之前我们讲线程安全的代码例⼦是这种形式]
当多个线程同时对某个资源进⾏CAS操作,只能有⼀个线程操作成功,但是并不会阻塞其他线程,其他线程只会收到操作失败的信号。

 CAS 可以视为是⼀种乐观锁. (或者可以理解成 CAS 是乐观锁的⼀种实现⽅式)

二、CAS 是怎么实现的  

针对不同的操作系统,JVM ⽤到了不同的 CAS 实现原理,简单来讲:
  • java 的 CAS 利⽤的的是 unsafe 这个类提供的 CAS 操作;
  • unsafe 的 CAS 依赖了的是 jvm 针对不同的操作系统实现的 Atomic::cmpxchg;
  • Atomic::cmpxchg 的实现使⽤了汇编的 CAS 操作,并使⽤ cpu 硬件提供的 lock 机制保证其原⼦性。
简⽽⾔之,是因为硬件予以了⽀持,软件层⾯才能做到

 

三、 CAS 有哪些应用

1) 实现原⼦类

标准库中提供了 java.util.concurrent.atomic 包, ⾥⾯的类都是基于这种⽅式来实现的.
典型的就是 AtomicInteger 类. 其中的 getAndIncrement 相当于 i++ 操作.
AtomicInteger atomicInteger = new AtomicInteger(0);
// 相当于 i++
atomicInteger.getAndIncrement();
假设两个线程同时调⽤ getAndIncrement
1、 两个线程都读取 value 的值到 oldValue 中. (oldValue 是⼀个局部变量, 在栈上. 每个线程有⾃⼰的栈)

2、线程1 先执⾏ CAS 操作. 由于 oldValue 和 value 的值相同, 直接进⾏对 value 赋值.  

注意:
  • CAS 是直接读写内存的, ⽽不是操作寄存器.
  • CAS 的读内存, ⽐较, 写内存操作是⼀条硬件指令, 是原⼦的.

 

3、线程2 再执⾏ CAS 操作, 第⼀次 CAS 的时候发现 oldValue 和 value 不相等, 不能进⾏赋值. 因此需要进⼊循环.
在循环⾥重新读取 value 的值赋给 oldValue

4、线程2 接下来第⼆次执⾏ CAS, 此时 oldValue 和 value 相同, 于是直接执⾏赋值操作. 

 

5、线程1 和 线程2 返回各⾃的 oldValue 的值即可. 

通过形如上述代码就可以实现⼀个原⼦类. 不需要使⽤重量级锁, 就可以⾼效的完成多线程的⾃增操作.

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

 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;}}

 

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

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

相关文章

日志集中审计系列(3)--- LogAuditor接收UMA设备syslog日志

日志集中审计系列(3)--- LogAuditor接收UMA设备日志 前言拓扑图设备选型组网需求配置思路操作步骤结果验证前言 近期有读者留言:“因华为数通模拟器仅能支持USG6000V的防火墙,无法支持别的安全产品,导致很多网络安全的方案和产品功能无法模拟练习,是否有真机操作的实验或…

PyCharm中出现Microsoft Defender配置建议

原因 Windows安全中心的病毒和威胁防护会自动扫描电脑中的文件夹,我们的项目文件夹和IDE文件夹也会被扫描,而PyCharm认为这会降低IDE性能。 解决方法 直接点击提示框里的自动。 或是手动给扫描添加排除项,步骤如下: 1、先打开…

k8s1.28.8版本配置Alertmanager报警方式(邮件,企业微信)

文章目录 总结部署流程 Alertmanager 三大核心1. 分组告警2. 告警抑制3. 告警静默 报警过滤静默通知方案一:方案二: 抑制报警规则案例一 参考文档 自定义路由告警,分来自不同路由的告警,艾特不同的人员进行区分修改 alertmanager …

预训练大模型最佳Llama开源社区中文版Llama2

Llama中文社区率先完成了国内首个真正意义上的中文版Llama2-13B大模型,从模型底层实现了Llama2中文能力的大幅优化和提升。毋庸置疑,中文版Llama2一经发布将开启国内大模型新时代。 作为AI领域最强大的开源大模型,Llama2基于2万亿token数据预…

【C++入门】输入输出、命名空间、缺省参数、函数重载、引用、内联函数、auto、基于范围的for循环

目录 命名空间 命名空间的定义 命名空间的使用 输入输出 缺省参数 函数重载 引用 常引用 引用的使用场景 内联函数 auto 基于范围的for循环 命名空间 请看一段C语言的代码&#xff1a; #include <stdio.h> #include <stdlib.h>int rand 10;int main…

图论-最短路

一、不存在负权边-dijkstra算法 dijkstra算法适用于这样一类问题&#xff1a; 从起点 start 到所有其他节点的最短路径。 其实求解最短路径最暴力的方法就是使用bfs广搜一下&#xff0c;但是要一次求得所有点的最短距离我们不可能循环n次&#xff0c;这样复杂度太高&#xf…

推挽输出与开漏输出

推挽输出与开漏输出 文章目录 推挽输出与开漏输出前言一、推挽输出二、开漏输出总结 前言 在使用GPIO口时&#xff0c;会遇到两种配置&#xff0c;一种叫推挽输出&#xff0c;一种叫开漏输出&#xff0c;今天就简聊一聊这两种模式的差异和选择。 一、推挽输出 如图所示&#…

力扣 1035. 不相交的线

题目来源&#xff1a;https://leetcode.cn/problems/uncrossed-lines/description/ C题解&#xff1a;经过细细一推导&#xff0c;就发现跟力扣 1143. 最长公共子序列-CSDN博客 换汤不换药。 直线不能相交&#xff0c;说明元素顺序不能改变&#xff0c;求可以绘制的最大连线数…

【数据结构与算法】二叉树遍历、判断和 diff 算法

遍历 深度优先遍历 function Node(value) {this.value valuethis.left nullthis.right null }let a new Node(a) let b new Node(b) let c new Node(c) let d new Node(d) let e new Node(e) let f new Node(f) let g new Node(g) a.left c a.right b c.l…

动态规划-最长回文子串

动态规划-最长回文子串 原题描述解答中心移动思想代码实现复杂度分析时间复杂度空间复杂度 动态规划思想代码实现复杂度分析时间复杂度空间复杂度 突然觉得很有必要将学过的内容记录下来&#xff0c;这样后续在需要用到的时候就可以避免从头进行学习&#xff0c;而去看自己之前…

鸿蒙OS开发实例:【ArkTS类库多线程I/O密集型任务开发】

使用异步并发可以解决单次I/O任务阻塞的问题&#xff0c;但是如果遇到I/O密集型任务&#xff0c;同样会阻塞线程中其它任务的执行&#xff0c;这时需要使用多线程并发能力来进行解决。 I/O密集型任务的性能重点通常不在于CPU的处理能力&#xff0c;而在于I/O操作的速度和效率。…

ESP8266 WiFi物联网智能插座—上位机软件实现

1、软件架构 上位机主要作为下位机数据上传服务端以及节点调试的控制端&#xff0c;可以等效认为是专属版本调试工具。针对智能插座协议&#xff0c;对于下位机进行可视化监测和管理。 软件技术架构如下&#xff0c;主要为针对 Windows 的PC 端应用程序&#xff0c;采用WPF以及…

HCIA复习

OSI --开放式系统互联参考模型 --- 7层参考模型 TCP/IP协议栈道 --- 4层或5层 OSI&#xff1a; 应用层 抽象语言 -->编码 表示层 编码-->二进制 表示层以下都是二进制-----data&#xff08;数据&#xff09; 会话层 提供应用程序的会话地址 上三层为应用…

七、函数的使用方法

函数的调用 nameinput&#xff08;&#xff09;#输入参数并赋值name print&#xff08;name&#xff09;#d打印name 格式&#xff1a;返回值函数名&#xff08;参数&#xff09; def get_sum(n):#形式参数计算累加和:param n::return: sumsum0for i in range(1,n1):sumiprint…

echarts 图表/SVG 图片指定位置截取

echarts 图表/SVG 图片指定位置截取 1.前期准备2.图片截取3.关于drawImage参数 需求&#xff1a;如下图所示&#xff0c;需要固定头部legend信息 1.前期准备 echarts dom渲染容器 <div :id"barchart id" class"charts" ref"barchart">&…

深入探索位图技术:原理及应用

文章目录 一、引言二、位图&#xff08;Bitset&#xff09;基础知识1、位图的概念2、位图的表示3、位图操作 三、位图的应用场景1、数据查找与存储2、数据去重与排序 四、位图的实现 一、引言 位图&#xff0c;以其高效、简洁的特性在数据处理、存储和检索等多个领域发挥着举足…

Mybatis常见面试题

1&#xff1a;Mybatis执行流程 回答&#xff1a; 读取Mybatis配置文件&#xff1a;mybatis-config.xml加载运行环境和映射文件构造会话工厂SqlSessionFactory会话工厂创建SqlSession对象&#xff08;包含了执行SQL语句的所有方法&#xff09;操作数据库的接口&#xff0c;Exec…

简单的链接中心软件yal

什么是 yal &#xff1f; yal(Yet Another Landingpage) 是一个简单的链接中心&#xff0c;用于显示和搜索链接。允许轻松打造品牌&#xff0c;以最少的权限运行并且易于使用。可以设置吉祥物和徽标&#xff08;目前是强制性的&#xff09;。 软件特点 静态生成的站点单个静态…

python通过shapely 的 valid 判断aoi图形是否有效

测试aoi坐标&#xff1a; 116.527712,39.924304;116.527123,39.924353;116.52707,39.923985;116.527685,39.92397;116.527712,39.924304 如图所示是一个有效的坐标&#xff0c;使用python代码判断是否有效&#xff1a; 代码&#xff1a; from shapely.geometry import Polyg…

CAJViewer7.3 下载地址及安装教程

CAJViewer是中国学术期刊&#xff08;CAJ&#xff09;全文数据库的专用阅读软件。CAJViewer是中国知识资源总库&#xff08;CNKI&#xff09;开发的一款软件&#xff0c;旨在方便用户在线阅读和下载CAJ数据库中的学术论文、期刊和会议论文等文献资源。 CAJViewer具有直观的界面…