CAS问题
CAS
- 🔎什么是CAS
- 🔎伪代码解析
- 🔎CAS是如何实现原子性的
- 🔎CAS的应用
- 🌻实现原子类
- 🌻实现自旋锁
- 🔎ABA问题
- 🌻ABA问题可能引起的BUG
- 🌻ABA问题的解决方案
- 🔎结尾
🔎什么是CAS
CAS
全称Compare and swap(比较并交换)
解释
寄存器A的值和内存B的值进行比较,如果值相同,就把寄存器C的值和内存B的值进行交换
🔎伪代码解析
boolean CAS(address, expectValue, swapValue) {if (&address == expectedValue) {&address = swapValue;return true;}return false;
}
解释

if ( &address == expectedValue)
如果寄存器A的值和内存B的值相等
&address = swapValue
将寄存器C的值与内存B的值交换
注意
上述代码只是伪代码,用来理解CAS的执行过程
针对上述代码,多线程情况下可能会引起安全问题
而CAS是原子性的,故不会引起安全问题
🔎CAS是如何实现原子性的
基于硬件(CPU)实现的原子性
🔎CAS的应用
🌻实现原子类
基于 java.util.concurrent.atomic 包中的类
一个典型的代表就是 AtomicInteger 类
举个栗子🥝
public static void main(String[] args) throws InterruptedException {AtomicInteger num = new AtomicInteger(0);int n = 50_000;Thread t1 = new Thread(() -> {for (int i = 0; i < n; i++) {//num++num.getAndIncrement();}}, "t1线程");Thread t2 = new Thread(() -> {for (int i = 0; i < n; i++) {//num++num.getAndIncrement();}}, "t2线程");t1.start();t2.start();t1.join();t2.join();System.out.println(num);}
针对上述代码
如果是非原子的自增操作(num++),就可能存在线程安全问题
但是由于CAS本身就是原子的,所以不会存在线程安全问题
也就是说,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;}
}
解释
Thread owner = null 代表当前的锁没有被线程持有
while(!CAS(this.owner, null, Thread.currentThread()))
Thread.currentThread() 代表当前线程
null 代表空
this.owner 代表当前锁
如果当前 owner 是null,就把当前线程的引用设置到 owner(加锁),循环结束
如果当前 owner 不是null,代表已经有其他线程加锁成功
此时就一直进行循环比较,不停的尝试加锁(速度很快)
public void unlock () 代表解锁
this.owner = null 解锁就是将owner设为null
🔎ABA问题
什么是ABA问题
通俗点来说就是从A变成了B最后又变成了A
A–>B–>A
CAS是对比内存和寄存器中的值,查看是否相同
(通过对比,判断内存中的值是否改变过)
但是对比时发现内存中的值是相同的,也不能确定内存中的值就没发生过改变
解释
t1线程读取内存中的值时,t2线程将内存中的值从A变成了B最后又变成了A
这时t1线程读取到的内存的值仍然是A,但是内存的值却发生了变化
这就是ABA问题
举个栗子🥝
我们买手机的时候
可能买到的是原装手机(没有更改的)
也可能买到的是翻新机—别人用了很久的,然后手机厂商进行一系列操作(换个壳,去去尘等),这样的手机看起来虽然和原装的没太大区别,但终究也只是看起来
原装手机就类似与内存中的值没有发生过改变
翻新机就类似于A–>B–>A
🌻ABA问题可能引起的BUG
举个栗子🥝
滑稽老哥去ATM机取款50元,他的银行账户有100元,取款之后变为50元
ATM并发执行两个线程
(1)线程1获取到当前存款为100元,执行扣款50元 线程2获取到当前存款为100元,执行扣款50元
(2)线程1执行扣款成功,滑稽老哥存款变为50 线程2阻塞等待
(3)此时正好滑稽老哥的朋友向滑稽老哥转账50元请滑稽老哥帮买东西
(4)滑稽老哥的存款又变为了100元
(5)线程2执行,发现存款仍为100元,执行扣款50元,此时滑稽老哥的账户又被扣款了50元
🌻ABA问题的解决方案
引入版本号,规定版本号只能增加
每次CAS对比的时候,不仅需要对比数值,而且需要对比版本号
如果进行修改数值,就将版本号+1
这样再去对比ABA问题时
发现版本号已经发生改变,就证明数值发生了变化
发现版本号没有发生改变,证明数值没有发生变化
举个栗子🥝
滑稽老哥去ATM机取款50元,他的银行账户有100元,取款之后变为50元
ATM并发执行两个线程,此时引入版本号,版本号为0
(1)线程1获取到当前存款为100元,执行扣款50元 线程2获取到当前存款为100元,执行扣款50元
(2)线程1执行扣款成功,滑稽老哥存款变为50 线程2阻塞等待,版本号变为1
(3)此时正好滑稽老哥的朋友向滑稽老哥转账50元请滑稽老哥帮买东西,版本号变为2
(4)滑稽老哥的存款又变为了100元
(5)线程2执行,发现存款仍为100元,但版本号发生了改变,此时就会执行失败
(6)滑稽老哥成功保住了50元
🔎结尾
创作不易,如果对您有帮助,希望您能点个免费的赞👍
大家有什么不太理解的,可以私信或者评论区留言,一起加油
相关文章:
CAS问题
CAS🔎什么是CAS🔎伪代码解析🔎CAS是如何实现原子性的🔎CAS的应用🌻实现原子类🌻实现自旋锁🔎ABA问题🌻ABA问题可能引起的BUG🌻ABA问题的解决方案🔎结尾&#…...
网络编程socket(下)
目录 一、TCP网络程序 1.1 服务端初始化 1.1.1 创建套接字 1.1.2 服务端绑定 1.1.3 服务端监听 1.2 服务端启动 1.2.1 服务端获取连接 1.2.2 服务端处理请求 1.3 客户端初始化 1.4 客户端启动 1.4.1 发起连接 1.4.2 发起请求 1.5 网络测试 1.6 单执行流服务端的…...
华为OD机试题【打折买水果】用 C++ 编码,速通
最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧本篇题解:打折买水果 题目 有 m m m…...
JSON 数据类型
JSON 数据类型 JSON 格式支持以下数据类型: 类型描述数字型(Number)JavaScript 中的双精度浮点型格式字符串型(String)双引号包裹的 Unicode 字符和反斜杠转义字符布尔型(Boolean)true 或 fal…...
Python函数简介
Python是一种高级编程语言,它的函数是其中一个非常重要的特性。在程序中,函数是一段被命名的代码块,它可以接受输入并且返回输出。本篇文章将介绍Python函数的基本概念、定义、调用和参数。 基本概念 在Python中,函数是由def关键…...
一文读懂 mysql 为什么要两阶段提交以及两阶段提交原理
文章目录 为什么要两阶段提交redo log与binlog两份日志之间的逻辑不一致,会出现什么问题?两阶段提交是怎么保证逻辑一致的呢?当 binlog 写完,redo log 还没 commit 前发生 crash,那崩溃恢复后 MySQL 如何处理?redo 与 binlog 的刷盘时机MySQL 的双 1 配置能否只用 redo l…...
启动Hadoop报错【Error: JAVA_HOME is not set and could not be found.】
当用了一下午从0安装上Hadoop兴奋的启动的时候! Error: JAVA_HOME is not set and could not be found. 他告诉我JAVA_HOME 没被找到? 我明明安装了java的,为什么找不到? java -version看了下发现是没问题的 解决: 后…...
《MySQL系列-InnoDB引擎35》索引与算法-B+树索引的使用
B树索引的使用 1 不同应用中B树索引的使用 在OLTP中,B树索引建立后,对该索引的使用应该只是通过该索引取得表中少部分的数据。这时建立B树索引才是有意义的,否则即使建立了,优化器也可能不选择使用索引。 在OLAP中,…...
【EHub_tx1_tx2_E100】不止科技NVISTAR ROC 300激光雷达Ubuntu18.04+ROS1ROS2 评测
介绍NVISTAR 的二维DTOF激光雷达 ROC 300在EHub_tx1_tx2_E100载板,TX1核心模块环境(Ubuntu18.04)下测试ROS1驱动和ROS2的驱动,打开使用RVIZ 查看点云数据,本文的前提条件是你的TX1里已经安装了ROS1版本:Mel…...
C语言函数大全--d开头的函数
C语言函数大全 本篇介绍C语言函数大全–d开头的函数 1. detectgraph 1.1 函数说明 函数声明函数功能void detectgraph(int *graphdriver, int *graphmode);通过检测硬件确定图形驱动程序和模式 1.2 演示示例 #include <graphics.h> #include <stdlib.h> #incl…...
基于springboot实现福聚苑社区团购演示【项目源码】
基于springboot实现福聚苑社区团购演示开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包&#…...
动静态库的制作
文章目录:什么是程序库?动态链接和静态链接动静态库的认识静态库的创建与使用创建使用动态库的创建与使用创建使用什么是程序库? 程序库:一般是软件作者为了发布方便、替换方便或二次开发目的,而发布的一组可以单独与应…...
QMS-云质-质量软件-客诉,为什么应该用两段式来处理
-云质QMS原创文章,转载请注明来源- 客户满意度是决定企业是否能够基业长青的关键因素之一。 如果客诉处理的不好,会极大影响客户的满意程度。 通常处理客诉分为两个阶段。 第一个阶段是快反遏制,想方设法快速答复和解决客户提出的问题&…...
JS:关于邮箱的正则表达式及规则
常用正则表达式—邮箱(Email) 要验证一个字符串是否为邮箱的话,首先要了解邮箱账号的格式。我尝试过在网上找出一个标准的格式,但是很遗憾我没有找到。我也尝试使用RFC标准来判断邮箱的格式,但是也没有结果。网上些博…...
两句话,ChatGPT帮我写一个打飞机的游戏
大家好,我是全村的希望今天的主题是让 chatGPT 来帮我们写一个打飞机的游戏记得我刚学 Python 的时候,看的那本很经典的入门书《Python 编程:从入门到实践》,里面就有小项目就是教你编写一个打飞机的游戏我那时候是对着书一个一个…...
计算机图形学14:三维图形的投影变换
作者:非妃是公主 专栏:《计算机图形学》 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩 文章目录专栏推荐专栏系列文章序一、三维图形的投…...
【ChatGPT4】王老师零基础《NLP》(自然语言处理)第二课
我的已经在起、点开了书《王老师带我成为救世主》,那个更新及时 (1)---------------------------------------------------------------------------------------- 我: 1我/喜欢/吃/苹果,因为/它/们/很/好吃。 2 Th…...
设计模式之中介者模式在前端的应用
文章目录中介者模式在前端的应用场景1.实现组件之间的松耦合2. 实现异步请求的协同3. 实现事件驱动的编程模型4. 实现复杂交互的协调总结中介者模式在前端的应用场景 中介者模式是一种常见的设计模式,它可以将对象之间的通信集中处理,从而提高系统的可维…...
2023年还能入行程序员吗?工作3年以上的黑马老学员怎么说?
很多人觉得,毕业3年,不过是毕业第1年的重复,键盘Ctrl、C和V键磨损更严重了。妥妥属于光涨年龄,不涨经验;只涨体重,不涨工资…… 他们不理解,为什么同样的起跑线,有人发展神速&#…...
接收机的噪声来源与噪声分析
噪声分类 射频接收机中的噪声主要可以分为两类:内部噪声和外部噪声。 内部噪声 内部噪声主要来自于接收机内部的放大器、混频器、本振等元件所产生的噪声。根据不同的产生机制,内部噪声可以分为以下几类: a. 电感噪声:由于电感…...
编程统计公司内部资料查阅使用数据,优化资料分类存储方式。提升职场员工工作查阅办事效率。
构建一个公司内部资料查阅使用统计与资料分类存储优化的商务智能示例项目,去营销化、中立化,仅用于学习与工程实践参考。一、实际应用场景描述在中大型企业中,内部资料(制度、流程文档、技术手册、项目档案)数量庞大&a…...
告别Python依赖!手把手教你用C++复现Librosa的Mel频谱和MFCC特征提取
高性能C音频特征提取实战:从Librosa原理到嵌入式部署优化 在语音识别和音频分析领域,Mel频谱和MFCC特征提取是基础但关键的技术环节。许多开发者习惯使用Python的Librosa库快速实现原型,但当需要部署到生产环境时,Python的解释器性…...
开源机械爪控制库:从PID算法到ROS集成的全栈开发指南
1. 项目概述:一个开源的机械爪设计与控制库最近在机器人硬件开发的圈子里,开源项目“MeyerZhou/openclaw”引起了不少创客和机器人爱好者的注意。简单来说,这是一个专注于机械爪(或称机械手、夹爪)设计与控制的代码库和…...
终极游戏性能调优指南:DLSS Swapper智能管理工具深度解析
终极游戏性能调优指南:DLSS Swapper智能管理工具深度解析 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 游戏体验痛点剖析:当DLSS版本成为性能瓶颈 你是否曾在畅玩《赛博朋克2077》时…...
JetBrains IDE 30天试用重置:一键解决方案的完整实践指南
JetBrains IDE 30天试用重置:一键解决方案的完整实践指南 【免费下载链接】ide-eval-resetter 项目地址: https://gitcode.com/gh_mirrors/id/ide-eval-resetter 当您正专注于代码调试时,IDE突然弹出"评估期已结束"的红色警告…...
Onekey:重构Steam Depot清单下载流程的现代化解决方案
Onekey:重构Steam Depot清单下载流程的现代化解决方案 【免费下载链接】Onekey Onekey Steam Depot Manifest Downloader 项目地址: https://gitcode.com/gh_mirrors/one/Onekey Onekey作为一款专为Steam Depot清单设计的自动化下载工具,通过其创…...
基于Rust与Candle的AI推理引擎cria:简化大模型本地部署与优化
1. 项目概述:从“左移”到“创造”的AI推理引擎 最近在折腾AI模型本地部署和推理优化的朋友,可能都绕不开一个名字: cria 。这个由 leftmove 开源的项目,全称是“Cria: The AI Inference Engine”,直译过来就是“创…...
如何永久保存你的微信聊天记录?WeChatExporter开源工具完整指南
如何永久保存你的微信聊天记录?WeChatExporter开源工具完整指南 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 你是否曾经历过手机丢失、微信重装后珍贵聊天…...
Claude模型思维链评估框架claweval:原理、实战与高级定制指南
1. 项目概述:一个专为Claude模型设计的“思维链”评估框架最近在AI应用开发圈里,一个名为claweval的项目开始被频繁提及。如果你正在使用Anthropic的Claude系列模型(无论是Claude 3 Opus、Sonnet还是Haiku)来构建需要复杂推理能力…...
基于Databerry的私有数据AI应用构建:从RAG原理到生产部署
1. 项目概述:一个开箱即用的AI应用构建平台如果你正在寻找一个能快速将私有数据(比如公司文档、个人笔记、产品手册)转化为智能问答机器人的工具,但又不想从零开始折腾复杂的向量数据库、嵌入模型和API集成,那么gmpetr…...
