关于CAS

什么是CAS:

CAS:Compare And Swap,比较且交换。

CAS中有三个参数:1.内存中原数据的值V  2.预期值A    3.修改后的数据B

Compare:V与A会先比较是否一样

Swap:如果V与A一致,那么就将B写入V

返回操作是否成功

伪代码:

public boolean CAS(int address,int expectValue,int swapValue){while(address == expectValue){address = swapValue;return true;}return false;}

值得注意的是:CAS并不是靠一段代码实现的,它其实是cpu里的一条指令完成的,且操作是原子性的,这就在一定程度上解决了线程安全的问题,故在以往加锁的基础上,又有一个新的选择来规避线程安全问题了


原子类:Atomic

自增操作伪代码:

class MyAtomicInteger{int value;public int getAndIncrement(){int oldValue = value;while(CAS(value,oldValue,oldValue+1) != true){oldValue = value;}//后置++  故不是返回+1后的值return oldValue;}
}

Java标准库中的atomic下的原子类,就是通过CAS来完成自增自减的操作的,此时不需要加锁,也是线程安全的

 public static void main(String[] args) throws InterruptedException {//原子类 基于CAS完成自增自减的操作 不用加锁 也是线程完全的AtomicInteger count = new AtomicInteger(0);Thread t1 = new Thread(() -> {for(int i = 0; i < 50000; i++){count.getAndIncrement(); // count++}});Thread t2 = new Thread(() -> {for(int i = 0; i < 50000; i++){count.getAndIncrement(); //count++}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}

我们来查看一下自增操作方法的源码:

 public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);}public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {var5 = this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));return var5;}public native int getIntVolatile(Object var1, long var2);

ps:native表示的是本地方法,其实现细节内容是由c++写的虚拟机中实现的

代码中的compareAndSwapInt就是我们上面所说的CAS操作了


自旋锁:

伪代码

public class mySpinLock {//自旋锁实现伪代码private Thread owner = null;public void lock(){while(!CAS(this.owner,null,Thread.currentThread())){//通过CAS可以知道当前锁是否被线程所有//如果此时锁已经被其他线程所有,那么此线程就会自旋等待CAS = false//如果此时锁资源是空闲的,那么就会owner设置为当前尝试加锁的线程}}public void unlock(){this.owner = null;}
}

CAS:检查当前的owner是否为null,为null就交换,将当前线程引用赋值给owner,循环结束,加锁完成,反之就会返回false,继续循环执行


ABA问题:

想象一个极端场景,我们在银行取钱的时候。使用CAS操作,此时有两个线程接收请求。

线程A:如果我有1000元,我取出500块钱,此时余额还是500(这时线程B阻塞)

再我第二次再准备取出五百前,有朋友又给我转了500,此时我的余额又变成了1000。

这个时候线程B开始运行(线程A阻塞):发现余额还是1000,那么久又会触发CAS操作,又给我扣了500块钱,此时卡里的余额只剩500了

这就是ABA的典型场景:值A被修改成了B  值被又被修改成了A   此时此A非彼A了

解决:添加一个版本号或者使用时间戳来判断当前版本,每次修改版本号+1。此时CAS的基准就变成了版本号,就非数据金额了(版本号没有改变,数据就没有被修改)

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

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

相关文章

[生活][杂项] 如何正确打开编织袋

编织袋打开的正确姿势 面对单线分离右边的线头&#xff0c;然后依次拉开即可

产品推荐 | 基于Lattice用于原型和FPGA设计和开发的Avant-E 评估板

01 产品概述 莱迪思半导体Avant-E评估板使设计人员能够快速进行原型设计和FPGA设计测试。它提供对所有 I/O 的访问&#xff0c;以及广泛的内存选项&#xff0c;以实现更快的原型设计和开发。 Avant-E评估板采用LFG1156封装的Avant-E FPGA。该板可以通过 FMC HPC、PMAD 和 Ras…

Claude 3 Opus 效果是否真的可以超过GPT-4?

实测,不仅是超过,而且我个人感觉这个差距甚至大于GPT3.5到GPT4的距离. claude3在长篇理学论文的解析能力是非常显著的,可以扩展补完作者省略的大量运用高等数学,复变函数以及更多数理方法的计算过程,并且将中间过程补完的非常完美.不会漏符号,错符号,偏差数值之类的问题.工科许…

ubuntu在xshell中使用快捷方式操作命令,减少命令行的数入量

第一步 第二步 然后无脑确定 第三步 在xshell的显示方式 方式一 这样就会在每个窗格中进行显示 方式二 效果显示–> 这种窗格的显示是全局的 然后你双击这个process就会自动把命令打在命令行上&#xff0c;减少你的输入量

【Gradle如何安装配置及使用的教程】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

新型大数据架构之湖仓一体(Lakehouse)架构特性说明——Lakehouse 架构(一)

文章目录 为什么需要新的数据架构&#xff1f;湖仓一体&#xff08;Lakehouse&#xff09;——新的大数据架构模式同时具备数仓与数据湖的优点湖仓一体架构存储层计算层 湖仓一体特性单一存储拥有数据仓库的查询性能存算分离开放式架构支持各种数据源类型支持各种使用方式架构简…

快速访问github

修改本地hosts文件 GitHub访问慢的原因在于域名解析&#xff0c;通过修改本地的hosts文件&#xff0c;将远程DNS解析改为本地DNS解析。 fang 步骤1&#xff1a;打开hosts文件&#xff08;没有就创建&#xff09; host所在位置&#xff1a; C:\Windows\System32\drivers\etc…

linux@内核@内核版本发展@镜像文件查看内核

文章目录 linux内核介绍简介小结 linux发行版和内核各个linux发行版和内核的关系内核更新追踪GAHWE版的内核 内核版本查看&#x1f60a;linux当前系统内核查看未安装时查看网络搜索内核版本号挂载镜像查看虚拟机启动镜像体验版查看内核版本 linux(内核)版本演进&#x1f60a;相…

python_列表和元组

介绍 列表&#xff08;List&#xff09;和元组&#xff08;Tuple&#xff09;是Python中两种不同的数据结构&#xff0c;它们都可以用来存储一系列的元素。下面是它们的主要特点和区别&#xff1a; 列表&#xff08;List&#xff09; 可变性&#xff1a;列表是可变的&…

【c基础】文件操作

1.fopen和fclose函数 函数原型 FILE *fopen(const char *path, const char *mode); 参数解释&#xff1a; 返回值&#xff1a;fopen打开成功&#xff0c;则返回有效file的有效地址&#xff0c;失败返回NULL。path是文件路径&#xff0c;可以相对路径&#xff0c;可以绝对路径…

C# 将 TextBox 绑定为 KindEditor 富文本

目录 关于 KindEditor 绑定设计 部署 KindEditor 实现代码 小结 关于 KindEditor KindEditor 基于JavaScript 编写&#xff0c;可以与众多WEB应用程序结合。KindEditor 依靠出色的用户体验和领先的技术提供富文本编辑功能&#xff0c;是一款非常受欢迎的HTML在线编辑器。…

400电话如何对接配置SIP

400电话对接配置SIP的基本步骤 要配置400电话对接SIP&#xff0c;通常需要遵循以下基本步骤&#xff1a; 注册和认证&#xff1a;首先需要在相应的云通信平台上注册账号&#xff0c;并进行企业实名认证。 开通语音服务&#xff1a;在通过认证后&#xff0c;需要开通语音服务&…

(007)Blender 根据顶点组分离模型

1.选中模型&#xff0c;并且进入【3D视图】【编辑模式】&#xff1a; 2.选择顶点组&#xff1a; 3.分离选中项&#xff1a;

【经验总结】Jupyter 配置内核

1. 背景描述 使用 国家超算互联网中心 的服务器&#xff0c;创建 jupyterlab 容器&#xff0c;想在之前 conda 创建的环境中运行&#xff0c;可是不行&#xff0c;进入容器就直接进入 jupyterlab 2. 解决方法 配置内核 2.1 激活环境 conda activate peft2.2 安装内核 pip…

易保全网络赋强公证系统,前置预防、快速化解债权纠纷

网络赋强公证是一种创新的法律服务模式&#xff0c;为金融机构和债权人提供了一种便捷、高效的债权保障方式。既可以加大对违约方的司法震慑力&#xff0c;又能降低维权方实现债权的风险&#xff0c;且执行时间更快&#xff0c;债权周期更短&#xff0c;诉讼费用更低&#xff0…

Oracle函数

Oracle 函数 一、SQL函数分类 二、单行函数字符函数数字函数日期函数转换函数to_charto_numberto_date 其它函数单行函数嵌套 三、组函数数据分组创建分组过滤分组&#xff08;having子句&#xff09;分组和排序 Selecct子句顺序 一、SQL函数 函数一般是在数据上执行的&#x…

Spring AI ETL 流水线

先纠正 Spring AI 使用本地 Ollama Embeddings 中的一个错误&#xff0c;当启动 Ollama 之后&#xff0c;Windows会有托盘图标&#xff0c;此时已经启动了 Ollama 的服务&#xff0c;访问 Embedding 时不需要运行 ollama run gemma &#xff0c;只有访问 chat 时才需要启动一个…

React脚手架的搭建与使用

React脚手架是开发现代Web应用的必备&#xff0c;其充分利用Webpack、Babel、ESlint等工具辅助项目的开发&#xff0c;当然这些工具也无需手动配置即可使用&#xff0c;脚手架的意义更多的是关注的是业务而不是工具的配置&#xff1b;项目的整体技术架构为&#xff1a;react w…

ZYNQ NVME高速存储之EXT4文件系统

前面文章分析了高速存储的各种方案&#xff0c;目前主流的三种存储方案是&#xff0c;pcie switch高速存储方案&#xff0c;zynq高速存储方案&#xff0c;fpga高速存储方案。虽然三种高速存储方案都可以实现高速存储&#xff0c;但是fpga高速存储方案是最烂的&#xff0c;fpga…

天软因子数据系列课堂回顾——“委托订单:流动性因子”

高频因子库4月更新&#xff0c;新增5张表单&#xff0c;51个因子。目前&#xff0c;高频因子数量扩容到628个&#xff0c;涵盖了从2000年开始的全A市场。本次“天软因子数据系列课堂”在线分享的即是最新发布因子列表之一的流动性因子&#xff0c;剖析微观角度下因子的底层逻辑…