当前位置: 首页 > news >正文

CAS的超~详细介绍

什么是CAS

CAS全称Compare and swap,是一种比较特殊的CPU指令.  字面意思:"比较并交换",

一个CAS涉及到以下操作:

我们假设内存中的原数据为V,旧的预期值A,需要修改的新值B.

1.比较A和V是否相等(比较)

2.如果相等,将B写入V.(交换)

3.返回操作是否成功.

伪代码

下面写的代码不是原子的,真实的CAS是一个原子的硬件指令完成的.这个伪代码只是辅助理解CAS的工作流程.

boolean CAS(address, expectValue, swapValue) {if(&address == expectedValue) {&address = swapValue;return true;}return false;
}

其中,address表示内存地址,expectValue和swapValue表示寄存器中的值.

流程就是比较address内存地址中的值是否与expect寄存器中的值相同.如果相同,就把swap寄存器中的值和address中的值进行交换(说是交换,实际上是赋值,其实完了之后我们往往只关注内存中的值,寄存器中的值,就不需要了),返回true.     如果不同,无事发生,返回false. 

CAS是怎么实现的

针对不同的操作系统,JVM用到了不同的CAS实现原理(操作系统对指令进行封装,JVM又对操作系统提供的api又封装了一层.),简单来讲:

java的CAS利用的是unsafe这个类提供的CAS操作;(这样的操作,涉及到一些系统底层内容,使用不当,可能会带来风险,一般不建议直接用CAS)

unsafe的CAS依赖了的是jvm针对不同的操作系统实现的Atomic::cmpxchg

Atomic::cmpxchg的实现使用了汇编的CAS操作,并使用cpu硬件提供的lock机制保证其原子性.

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

CAS有哪些应用

实现原子类

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

AtomicInteger atomicInteger = new AtomicInteger(0);
//相当于i++操作(但实际上只是一个指令,它天然是原子的)
atomicInteger.getAndIncrement();

伪代码实现:

class AtomicInteger {private int value;public int getAndIncrement() {int oldValue = value;//发现value与oldValue不同.意味着CAS之前另一个线程修改了value//通过该方式,能意识到被修改while ( CAS(value, oldValue, oldValue + 1) != true) {oldValue = value;}//发现value被修改过,就重新读取新的value到OldValue中return oldValue;}
}

假设两个线程同时调用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的值即可.

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

实现自旋锁

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

public class SpinLock {private Thread owner = null;public void lock() {//通过CAS看当前锁是否被某个线程持有.//如果这个锁已经被别的线程持有,那么就自旋等待.//如果这个锁没有被别的线程持有,那么就把owner设为当前尝试加锁的线程while(!CAS(this.owner, null, Thread.currentThread())) {//当owner不为null的时候,循环就会一直执行下去,通过这样的"忙等"来完成等待效果}//阻塞式的等.让线程不参与cpu调度了,此处自旋式的等,没有放弃cpu//不会参与到调度,也就没有了调度开锁了.但缺点就是消耗了更多的cpu       public void unlock() {this.owner = null;}}
}

CAS的ABA问题

什么是ABA问题

ABA的问题:

假设存在两个线程t1,t2.有一个共享变量num,初始值为A.

接下来,线程t1想使用CAS把num变成Z,那么就需要

先读取num的值,记录到oldNum变量中

使用CAS判定当前num的值是否为A,如果为A,就要修改成Z. 

但是,在t1执行这两个操作之间,t2线程可能把num的值从A改成了B,又从B改成了A.

线程t1的CAS期望num不变就修改.但是num的值已经被t2给改了.只不过又改成A了.这个时候t1究竟是否要更改num的值为Z呢? 

到这一步,t1线程无法区别当前这个变量始终是A,还是经历了一个变化过程

这就好比,我们买一个手机,无法判定这个手机是刚出厂的新手机,还是别人用旧了,又翻新过的手机.

ABA问题引来的BUG 

 大部分情况下,t2线程这样的一个反复横跳改动,对于t1是否修改num是没有影响的.但是不排除一些特殊情况.

假设一个人有1000元存款,他想从中取出500块钱.

取钱的时候ATM卡了,按了一下没反应(t1),又按了一下(t2)还是没反应

按理来说这应该是正常的.

1.存款1000,线程1获取到当前存款值1000,期望更新为500;线程2获取到当前存款值1000,期望更新为500.

2.线程1执行成功.存款被改为500,线程2阻塞等待中.

3.轮到线程2执行了,发现当前存款为500,与之前读到的1000不同,执行失败.

但如果出现了极端情况:比如中间有人给你转了500.

这个时候线程2发现当前存款为1000,与1000相同,又扣款了一次.

这个时候,就被扣款了两次,这都是ABA问题搞的鬼!!

解决方案

1.约定数据的变化是单向的(只能增加或者只能减少),不是双向的(既能增加又能减少)

2.给要修改的值,引入版本号.在CAS比较当前值与旧值的同时,也要比较版本号是否符合预期.

  (1)CAS操作在读取旧值的同时,也要读取版本号

  (2)真正修改的时候,

                如果当前版本号和读到的版本号相同,就修改数据,并把版本号+1

                如果当前版本号高读到的版本号.就操作失败(认为数据已经被修改过了)

相关面试题

1.讲解下你自己了解的CAS机制

全程Compare and swap, 即"比较并交换".相当于通过一个原子的操作,同时完成"读取内存,比较是否相等,修改内存"这三个步骤.本质上需要CPU指令的支撑

2.ABA问题怎么解决

给要修改的数据引入版本号.在CAS比较当前值和旧值的同时,也要比较版本号是否符合预期.如果返现当前版本号和之前读到的版本号一致,就真正执行修改操作,并让版本号自增;如果发现当前版本号比之前大,则视为操作失败 

相关文章:

CAS的超~详细介绍

什么是CAS CAS全称Compare and swap,是一种比较特殊的CPU指令. 字面意思:"比较并交换", 一个CAS涉及到以下操作: 我们假设内存中的原数据为V,旧的预期值A,需要修改的新值B. 1.比较A和V是否相等(比较) 2.如果相等,将B写入V.(交换) 3.返回操作是否成功. 伪代码 下面…...

Scott用户数据表的分析

Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 如果想要知道某个用户所有的数据表: select * from tab; 此时结果中一共返回了四张数据表,分别为部门表(dept) ,员工表(emp&a…...

网络基础学习(3):交换机

1.交换机结构 (1)网线接口和后面的电路部分加在一起称为一个端口,也就是说交换机的一个端口就相当于计算机上的一块网卡。 如果在计算机上安装多个网卡,并让网卡接收所有网络包,再安装具备交换机功能的软件&#xff0…...

【软件测试学习笔记2】用例设计方法

1.能对穷举场景设计测试点(等价法) 等价类: 说明:在所有测试数据中,具有某种共同特征的数据集合进行划分 分类:有效等价类:满足需求的数据集合 无效等价类:不满足需求的数据集合 步…...

蓝桥杯 第三场 小白入门赛

召唤神坤 有意思🤔(ikun)。虽然是第一题但也要配得上神坤的身份。 思路1 枚举分母,选择一个数据结构来选出分母两侧最大的两个数做分子。2s常数大些也无碍。我选择好写的ST表 思路2 写两个 d p dp dp 分别表示 1 1 1 到 i…...

网络安全等级保护测评规划与设计

笔者单位网络结构日益复杂,应用不断增多,使信息系统面临更多的风险。同时,网络攻防技术发展迅速,攻击的技术门槛随着自动化攻击工具的应用也在不断降低,勒索病毒等未知威胁也开始泛滥。基于此,笔者单位拟进…...

Error: Cannot find module ‘vue-template-compiler‘ 问题解决

启动Vuepress项目时报了如下错误:Error: Cannot find module vue-template-compiler Error: Cannot find module vue-template-compiler Require stack: - /usr/local/lib/node_modules/vuepress/node_modules/vue-loader/lib/compiler.js - /usr/local/lib/node_…...

华为认证云计算专家(HCIE-Cloud Computing)--练习题

华为认证云计算专家(HCIE-Cloud Computing)–练习题 1.(判断题)华为云stack支持鲲鹏架构,业务可从X86过渡到鲲鹏。 正确答案:正确 2.(判断题)业务上云以后,安全方面由云服务商负责,客户自己不需要做任何防…...

【MATLAB】【数字信号处理】产生系统的单位冲激响应h(t)与H(z)零极点分布

一、实验目的与要求 产生h(t) 与H(z) 零极点分布 二、实验仪器 微机,仿真软件MATLAB 2022a 三、实验内容与测试结果 1.已知描述连续系统的微分方程为y(t)5y(t)6y(t)2x(t)8x(t) ,计算系统的单位冲激响应h(t) 程序如下: clear all; ts0;…...

实验五:动态路由配置

实验五:动态路由配置 1.RIP 配置 【实验名称】 RIP 路由协议配置 【实验目的】掌握路由器 RIP 路由协议的基本配置 【实验设备】路由器( 2 台)、计算机( 2 台)、配置电缆( 1 根)、 V…...

苍穹外卖学习----出错记录

1.微信开发者工具遇到的问题: 1.1appid消失报错: {errMsg: login:fail 系统错误,错误码:41002,appid missing [20240112 16:44:02][undefined]} 1.2解决方式: appid可在微信开发者官网 登录账号后在开发栏 找到 复制后按以下步骤粘贴即…...

如何实现图片压缩

文章目录 1、canvas实现图片压缩2、其他 1、canvas实现图片压缩 canvas 实现图片压缩,主要是使用 canvas 的drawImage 方法 具体思路 拿到用户上传的文件转成base64创建一个 Image,主要是获取到这个图片的宽度和高度创建一个 2D 的画布,画布…...

机器学习算法实战案例:时间序列数据最全的预处理方法总结

文章目录 1 缺失值处理1.1 统计缺失值1.2 删除缺失值1.3 指定值填充1.4 均值/中位数/众数填充1.5 前后项填充 2 异常值处理2.1 3σ原则分析2.2 箱型图分析 3 重复值处理3.1 重复值计数3.2 drop_duplicates重复值处理 3 数据归一化/标准化3.1 0-1标准化3.2 Z-score标准化 技术交…...

MongoDB高级集群架构设计

两地三中心集群架构设计 容灾级别 RPO & RTO RPO(Recovery Point Objective):即数据恢复点目标,主要指的是业务系统所能容忍的数据丢失量。RTO(Recovery Time Objective):即恢复时间目标&…...

C++中JSON与string格式互转

1、JSON-》string 操作步骤&#xff1a; 1、在C中新建一个json对象并赋值&#xff0c;然后将其转给char *data。 2、在使用 #include <json.h> 头文件时&#xff0c;通常是使用第三方库 jsoncpp。由于它不是标准库的一部分&#xff0c;所以需要从官网http://jsoncpp.sou…...

2023一带一路暨金砖国家技能发展与技术创新大赛 【企业信息系统安全赛项】国内赛竞赛样题

2023一带一路暨金砖国家技能发展与技术创新大赛 【企业信息系统安全赛项】国内赛竞赛样题 2023一带一路暨金砖国家技能发展与技术创新大赛 【企业信息系统安全赛项】国内赛竞赛样题第一阶段&#xff1a; CTF 夺旗项目1. CTF 夺旗任务一 命令注入任务二 SQL 注入 项目2. 序列化漏…...

【BBuf的CUDA笔记】十二,LayerNorm/RMSNorm的重计算实现

带注释版本的实现被写到了这里&#xff1a;https://github.com/BBuf/how-to-optim-algorithm-in-cuda/tree/master/apex 由于有很多个人理解&#xff0c;读者可配合当前文章谨慎理解。 0x0. 背景 我也是偶然在知乎的一个问题下看到这个问题&#xff0c;大概就是说在使用apex的…...

安装Mac提示安装无法继续,因为安装器已损坏

目录 事件起因报错原因 事件起因 有两台电脑&#xff0c;由于电脑1下载镜像文件很快&#xff0c;于是我先用电脑1下载这个大文件&#xff0c;然后安装openresty&#xff0c;电脑2用http链接下载这个大文件。电脑2安装中途就报安装无法继续,因为安装器已损坏。 报错原因 不知…...

脚本编程游戏引擎会遇到哪些问题

在游戏开发中&#xff0c;脚本编程已经成为了一种非常常见的方式&#xff0c;用来实现游戏逻辑和功能。但是脚本编程游戏引擎也可能会面临一些挑战和问题。下面简单的探讨一下都会遇到哪些问题&#xff0c;并且该如果做。 性能问题 脚本语言通常需要运行时解释执行&#xff0…...

什么软件可以做报表?

数据报表&#xff0c;是商业领域中不可或缺的一部分&#xff0c;它通过表格、图表等形式&#xff0c;将复杂的数据进行整理、分析并呈现出来&#xff0c;帮助用户更好地理解数据的趋势和关系。数据报表不仅展示了业务现状和趋势&#xff0c;还支持多种数据分析和挖掘功能&#…...

千问 LeetCode 2281.巫师的总力量和 public int totalStrength(int[] strength)

LeetCode 2281. 巫师的总力量和 是一道经典的 贡献法 + 单调栈 + 前缀和的前缀和 题目。题目要求对数组的所有非空连续子数组,计算: min(subarray) * sum(subarray) 的总和,并对 10^9 + 7 取模。 ✅ 解题思路(核心思想) 我们 不枚举所有子数组(那样是 O(n)),而是 枚…...

【AI工具推荐】Awesome DESIGN.md - 让AI生成像素级完美UI的设计神器

有兴趣的朋友&#xff0c;点点关注。每天分享一个AI工具。每天分享一个AI工具&#xff0c;今天推荐&#xff1a;Awesome DESIGN.md - 一个让AI代理能够生成像素级完美UI的开源设计系统集合项目简介 Awesome DESIGN.md 是一个精心策划的DESIGN.md文件集合&#xff0c;灵感来源于…...

MTKClient实战指南:联发科设备刷机与逆向工程全面解决方案

MTKClient实战指南&#xff1a;联发科设备刷机与逆向工程全面解决方案 【免费下载链接】mtkclient MTK reverse engineering and flash tool 项目地址: https://gitcode.com/gh_mirrors/mt/mtkclient MTKClient是一款专为联发科芯片设备设计的开源逆向工程与刷机工具&am…...

硬件工程师显示器选购指南:从垂直分辨率到IPS面板的实战经验

1. 从“够用”到“爽用”&#xff1a;一个硬件工程师的显示器升级心路作为一名整天和代码、电路图、数据手册打交道的硬件工程师&#xff0c;我的工作台就是我的战场。而这块战场上最核心的装备&#xff0c;除了键盘鼠标&#xff0c;就是那块每天要盯着看至少八小时的显示器。几…...

保边滤波深度学习红外可见光融合算法【附程序】

✨ 长期致力于红外与可见光图像融合、快速引导滤波器、交替引导滤波器、深度学习、卷积神经网络研究工作&#xff0c;擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流&#xff0c;点击《获取方式》 &#xff08;1&#xff09;双支流…...

工程师实战:Windows 8工作站部署、驱动危机与专业工具兼容性全解析

1. 从工程师视角看Windows 8的喧嚣与真实2013年&#xff0c;当Windows 8带着那个被称为“Metro”的崭新界面横空出世时&#xff0c;整个科技圈&#xff0c;尤其是我们这些整天和硬件、设计工具打交道的工程师群体&#xff0c;几乎炸开了锅。媒体上充斥着两极分化的评价&#xf…...

技术奇点之后,人类程序员的历史角色

当人工智能越过技术奇点&#xff0c;代码生成、测试用例设计乃至系统运维都将发生质变。本文从软件测试从业者的视角出发&#xff0c;系统探讨人类程序员在奇点之后可能扮演的六种核心角色&#xff1a;系统守护者、需求翻译官、质量伦理法官、人机交互设计师、持续学习组织者与…...

从CuteCom到代码:手把手教你用I.MX6ULL实现串口双向通信(附完整工程源码)

从CuteCom到代码&#xff1a;手把手教你用I.MX6ULL实现串口双向通信&#xff08;附完整工程源码&#xff09; 在嵌入式开发中&#xff0c;串口通信是最基础也最常用的调试手段之一。无论是简单的数据收发&#xff0c;还是复杂的协议交互&#xff0c;串口都能提供稳定可靠的通信…...

Steam Cron Studio:可视化配置生成器,为AI代理打造Steam自动化任务

1. Steam Cron Studio&#xff1a;一个为AI代理量身定制的Steam自动化配置生成器如果你是一个Steam重度用户&#xff0c;同时又对AI代理&#xff08;AI Agent&#xff09;和自动化工具感兴趣&#xff0c;那么你很可能和我一样&#xff0c;曾经被一个看似简单实则繁琐的问题困扰…...

为OpenClaw智能体工作流配置Taotoken作为统一的模型调用后端

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 为OpenClaw智能体工作流配置Taotoken作为统一的模型调用后端 对于使用OpenClaw框架构建AI智能体的开发者而言&#xff0c;一个稳定…...