关于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;然后依次拉开即可

java 中的 Math.round(-1.5) 等于多少?

Math提供了三个与取整有关的方法&#xff1a;ceil、floor、round &#xff08;1&#xff09;ceil&#xff1a;向上取整&#xff1b; Math.ceil(11.3) 12; Math.ceil(-11.3) 11; &#xff08;2&#xff09;floor&#xff1a;向下取整&#xff1b; Math.floor(11.3) 11; …

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

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

vue--样式绑定--样式切换方法

1.通过改变类名的方法改变盒子样式 可以通过 :class变量名来动态改变标签的样式名&#xff0c;变量值可以是字符串、数组、对象 1.字符串写法 适用于样式类名不确定需要动态指定 <div classbase :classa>Text</div> data:{ a:normal } classbase和 :classa可…

【C语言】数组相关选择题

目录 前言 题目一&#xff1a; 题目二&#xff1a; 题目三&#xff1a; 题目四&#xff1a; 题目五&#xff1a; 题目六&#xff1a; 题目七&#xff1a; 题目八&#xff1a; 题目九&#xff1a; 题目十&#xff1a; 前言 一些数组选择题 题目一&#xff1a; 关于数…

Java程序实现多语言资源JSON文件生成

你好呀&#xff0c;我是小邹。 在现代软件开发中&#xff0c;实现应用程序的多语言支持是一项基本需求&#xff0c;以适应全球用户的语言环境。本文将介绍一段Java代码&#xff0c;其主要功能是生成一个特定格式的JSON文件&#xff0c;用于存储和管理中英文双语对照的键值对&a…

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

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

ModuleNotFoundError: No module named ‘cv2‘

python运行到下面这一句“import cv2”时报错&#xff1a; >>> import cv2 Traceback (most recent call last):File "<stdin>", line 1, in <module> ModuleNotFoundError: No module named cv2 解决方法&#xff1a; 安装扩展包&#xff0…

基于K-prototype算法聚类

k-prototype聚类是一种用于混合数据类型聚类的算法&#xff0c;由Jain和Dubes在1988年提出。它主要用于同时包含连续属性和离散属性的数据集。k-prototype算法可以看作是k-means算法的扩展&#xff0c;它将k-means算法的思想应用于混合数据类型&#xff0c;通过为连续属性和离散…

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

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

Oracle数据库Bug:相关子查询多层嵌套报错:标识符无效

Oracle Bug? 一、案例描述二、解决方案<一>、升级版本<二>、改写语句 一、案例描述 在Mysql中常常有如下写法用相关子查询 order by desc limit 1来完成需求 select code,date,(select value from test t1 where t.code t1.code and t1.date between date_su…

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

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

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

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

递归求阶乘和(不熟悉)

本题要求实现一个计算非负整数阶乘的简单函数&#xff0c;并利用该函数求 1!2!3!...n! 的值。 函数接口定义&#xff1a; double fact( int n ); double factsum( int n ); 函数fact应返回n的阶乘&#xff0c;建议用递归实现。函数factsum应返回 1!2!...n! 的值。题目保证输…

快速访问github

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

1031:反向输出一个三位数

#include<bits/stdc.h> using namespace std; int main() {int a;cin>>a;cout<<a%10;cout<<a/10%10;cout<<a/100%10;return 0; } 时间限制: 1000 ms 内存限制: 65536 KB 提交数:146171 通过数: 89399 【题目描述】 将一个三位数反向…

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在线编辑器。…