CAS算法-实现原理

article/2025/8/30 2:59:54

目录

CAS是什么?

CAS解决了什么问题?

CAS存在什么问题?

CAS有哪些应用场景?

cas的实现

最后


CAS是什么?

    CAS的全称为Compare and swap 比较并交换。CAS又经常被称为乐观锁,主要的三个变量,内存值V,旧的预期值P,需要修改的新值N,原理就是:当 P等于V ,则将 N值赋给 V;

(个人理解:当你修改密码时,你的旧密码跟你输入的一致才能更换!)

47fe51246647fd26848f5c7af4679043.png

CAS解决了什么问题?

    解决并发访问中无锁的非阻塞算法的实现。

CAS存在什么问题?

    ABA问题:添加版本号解决;其实就是乐观锁;

    解决方案:通过添加版本号来解决。

    内存开销大:若并发过大,会导致内存开销很大;

CAS有哪些应用场景?

    jdk默认自带的Atomick开头的实现类底层都是使用了CAS算法;

    自旋锁的实现,底层也是通过CAS轮询的方式进行实现;

cas的实现

    存在ABA问题的实现方式:

/*** @author: csh* @Date: 2022/8/6 21:05* @Description: cas工具类 该类存在一个缺陷,没有版本控制会导致aba问题*/
public class CasV1 {//内存的值private int value;//获取值public synchronized int getValue() {return value;}//对比值并且设置值public synchronized int compareAndSwap(int defaultValue,int newValue){int oldValue = value;if(oldValue == defaultValue){this.value = newValue;}return oldValue;}//对比值public synchronized boolean compareAndSet(int defaultValue,int newValue){return defaultValue==compareAndSwap(defaultValue,newValue);}
}
}

验证

/*** @author: csh* @Date: 2022/8/6 21:03* @Description:cas实现验证*/
public class CasStudy {public static void main(String[] args) {CasV1 casV1 = new CasV1();for (int i = 0; i < 100; i++) {new Thread(new Runnable() {@Overridepublic void run() {int defaultValue = casV1.getValue();int newValue = (int) (Math.random() * 10000);boolean setResult = casV1.compareAndSet(defaultValue,newValue );System.out.println("新值:"+newValue+"设置结果为:" + setResult);}}).start();}}
}

结果

新值:2558设置结果为:true
新值:6016设置结果为:true
新值:6498设置结果为:false
新值:5326设置结果为:false
新值:9294设置结果为:true
新值:7897设置结果为:true
新值:6352设置结果为:true
新值:8844设置结果为:false
新值:1935设置结果为:true
新值:1502设置结果为:false
新值:8283设置结果为:false
新值:943设置结果为:true
新值:1600设置结果为:false
新值:7259设置结果为:true
新值:8898设置结果为:false
新值:9597设置结果为:false
新值:8883设置结果为:true
新值:4458设置结果为:true
新值:7120设置结果为:true
新值:5546设置结果为:false
新值:2138设置结果为:true
新值:8985设置结果为:false
新值:5666设置结果为:true
新值:3799设置结果为:false
新值:2267设置结果为:true
新值:1585设置结果为:false
新值:4961设置结果为:false
新值:9770设置结果为:false
新值:4449设置结果为:true
新值:4370设置结果为:true
新值:7385设置结果为:true
新值:9800设置结果为:true
新值:7130设置结果为:true
新值:7106设置结果为:true
新值:8088设置结果为:true
新值:894设置结果为:false
新值:639设置结果为:true
新值:7351设置结果为:true
新值:1438设置结果为:true
新值:2947设置结果为:true
新值:9486设置结果为:true
新值:845设置结果为:true
新值:7280设置结果为:true
新值:664设置结果为:true
新值:1971设置结果为:true
新值:6174设置结果为:true
新值:3707设置结果为:true
新值:8093设置结果为:true
新值:3523设置结果为:true
新值:8760设置结果为:true
新值:5516设置结果为:true
新值:4813设置结果为:true
新值:9809设置结果为:true
新值:6009设置结果为:true
新值:9110设置结果为:true
新值:4006设置结果为:true
新值:5954设置结果为:true
新值:4544设置结果为:true
新值:3239设置结果为:true
新值:7333设置结果为:true
新值:3658设置结果为:true
新值:5678设置结果为:true
新值:3892设置结果为:true
新值:1269设置结果为:true
新值:139设置结果为:true
新值:5508设置结果为:true
新值:4191设置结果为:true
新值:2466设置结果为:true
新值:319设置结果为:true
新值:1743设置结果为:true
新值:9549设置结果为:true
新值:75设置结果为:true
新值:4112设置结果为:true
新值:334设置结果为:true
新值:5523设置结果为:true
新值:3719设置结果为:true
新值:2367设置结果为:true
新值:2669设置结果为:true
新值:819设置结果为:true
新值:6787设置结果为:true
新值:2509设置结果为:true
新值:4291设置结果为:true
新值:735设置结果为:true
新值:6104设置结果为:true
新值:354设置结果为:true
新值:6324设置结果为:true
新值:6938设置结果为:true
新值:630设置结果为:true
新值:2881设置结果为:true
新值:6367设置结果为:true
新值:7941设置结果为:true
新值:3855设置结果为:true
新值:7853设置结果为:true
新值:6457设置结果为:true
新值:901设置结果为:true
新值:6800设置结果为:true
新值:9424设置结果为:true
新值:1911设置结果为:true
新值:1131设置结果为:true
新值:91设置结果为:true

解决ABA问题的版本。

package com.hong.arithmetic.cas;import java.util.concurrent.atomic.AtomicReference;/*** @author: csh* @Date: 2022/8/6 21:05* @Description: cas工具类 通过jdk自带AtomicReference 实现*/
public class CasV2 {public CasV2() {}public CasV2(AtomicReference<Integer> value) {this.value = value;}//内存的值AtomicReference<Integer> value;//获取值public Integer getValue() {return value.get();}//对比值public boolean compareAndSet(int defaultValue, int newValue) {return value.compareAndSet(defaultValue, newValue);}}

运行

//解决ABA问题的版本
CasV2 casV2 = new CasV2(new AtomicReference<>(10));
for (int i = 0; i < 100; i++) {new Thread(new Runnable() {@Overridepublic void run() {int defaultValue = casV2.getValue();int newValue = (int) (Math.random() * 10000);boolean setResult = casV2.compareAndSet(defaultValue,newValue );System.out.println("ABA版本新值:"+newValue+"设置结果为:" + setResult);}},"ABA").start();
}

结果

ABA版本新值:8648设置结果为:false
ABA版本新值:1194设置结果为:false
ABA版本新值:7614设置结果为:false
ABA版本新值:2322设置结果为:false
ABA版本新值:7366设置结果为:true
ABA版本新值:1427设置结果为:false
ABA版本新值:2877设置结果为:false
ABA版本新值:5098设置结果为:false
ABA版本新值:1592设置结果为:false
ABA版本新值:2739设置结果为:false
ABA版本新值:1654设置结果为:false
ABA版本新值:8171设置结果为:false
ABA版本新值:2893设置结果为:false
ABA版本新值:3774设置结果为:false
ABA版本新值:8768设置结果为:false
ABA版本新值:3924设置结果为:false
ABA版本新值:397设置结果为:false
ABA版本新值:6727设置结果为:false
ABA版本新值:1518设置结果为:false
ABA版本新值:2734设置结果为:false
ABA版本新值:5193设置结果为:false
ABA版本新值:9006设置结果为:false
ABA版本新值:2832设置结果为:false
ABA版本新值:1447设置结果为:false
ABA版本新值:2595设置结果为:false
ABA版本新值:1559设置结果为:false
ABA版本新值:3129设置结果为:false
ABA版本新值:2254设置结果为:false
ABA版本新值:420设置结果为:false
ABA版本新值:2362设置结果为:false
ABA版本新值:3229设置结果为:false
ABA版本新值:4724设置结果为:false
ABA版本新值:5974设置结果为:false
ABA版本新值:4991设置结果为:false
ABA版本新值:1195设置结果为:false
ABA版本新值:4314设置结果为:false
ABA版本新值:9551设置结果为:false
ABA版本新值:1287设置结果为:false
ABA版本新值:4683设置结果为:false
ABA版本新值:1418设置结果为:false
ABA版本新值:3393设置结果为:false
ABA版本新值:7038设置结果为:false
ABA版本新值:7149设置结果为:false
ABA版本新值:5323设置结果为:false
ABA版本新值:3281设置结果为:false
ABA版本新值:5904设置结果为:false
ABA版本新值:8933设置结果为:false
ABA版本新值:5726设置结果为:false
ABA版本新值:8065设置结果为:false
ABA版本新值:5671设置结果为:false
ABA版本新值:2667设置结果为:false
ABA版本新值:1780设置结果为:false
ABA版本新值:9494设置结果为:false
ABA版本新值:664设置结果为:false
ABA版本新值:264设置结果为:false
ABA版本新值:7175设置结果为:false
ABA版本新值:3667设置结果为:false
ABA版本新值:8690设置结果为:false
ABA版本新值:3084设置结果为:false
ABA版本新值:3851设置结果为:false
ABA版本新值:1720设置结果为:false
ABA版本新值:9836设置结果为:false
ABA版本新值:4408设置结果为:false
ABA版本新值:308设置结果为:false
ABA版本新值:1583设置结果为:false
ABA版本新值:5942设置结果为:false
ABA版本新值:8630设置结果为:false
ABA版本新值:4310设置结果为:false
ABA版本新值:502设置结果为:false
ABA版本新值:1471设置结果为:false
ABA版本新值:6506设置结果为:false
ABA版本新值:5214设置结果为:false
ABA版本新值:9084设置结果为:false
ABA版本新值:4223设置结果为:false
ABA版本新值:2937设置结果为:false
ABA版本新值:2837设置结果为:false
ABA版本新值:4354设置结果为:false
ABA版本新值:811设置结果为:false
ABA版本新值:7374设置结果为:false
ABA版本新值:125设置结果为:false
ABA版本新值:8256设置结果为:false
ABA版本新值:9112设置结果为:false
ABA版本新值:9827设置结果为:false
ABA版本新值:8817设置结果为:false
ABA版本新值:1897设置结果为:false
ABA版本新值:3784设置结果为:false
ABA版本新值:1233设置结果为:false
ABA版本新值:1902设置结果为:false
ABA版本新值:7025设置结果为:false
ABA版本新值:5885设置结果为:false
ABA版本新值:5254设置结果为:false
ABA版本新值:4337设置结果为:false
ABA版本新值:9677设置结果为:false
ABA版本新值:1991设置结果为:false
ABA版本新值:7234设置结果为:false
ABA版本新值:1155设置结果为:false
ABA版本新值:861设置结果为:false
ABA版本新值:9570设置结果为:false
ABA版本新值:9935设置结果为:false
ABA版本新值:1030设置结果为:false

可以看到只有一个成功,所以底层可以通过while循环方式进行重新获取最新进行判断。

看看jdkAtomicInteger底层的实现

//这里底层通过 unsafe来实现,这个是由c++来写的所以看不到。
public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

但是可以通过其他方法发现,很多都是通过先获取当前值,然后去判断是否设置成功,如果没成功通过轮训方式进行设置,直到成功为止,所以用这个CAS会导致cpu飙高的原因就在这里。

public final int getAndUpdate(IntUnaryOperator updateFunction) {int prev, next;do {prev = get();next = updateFunction.applyAsInt(prev);} while (!compareAndSet(prev, next));return prev;
}

最后

    cas在算法在很多一些基础的开发都会用到,只是现在Jdk默认有Atomic这个包,通过这个包已经为我们实现了功能,我们可以很方便引用已封装好的包进行实现,本文主要讲解原理。不过在使用cas上面有一点需要特别注意,因为cas如果很多处同时在包循环会导致cpu飙高,所以这点特别重要,一些公司有cpu监控的,要特别注意,避免频繁告警或者因为原来已经很高的cpu导致打到100%,那就很可能引发事故。


http://chatgpt.dhexx.cn/article/J9YWdl8K.shtml

相关文章

并发策略-CAS算法

对于并发控制而言&#xff0c;我们平时用的锁&#xff08;synchronized&#xff0c;Lock&#xff09;是一种悲观的策略。它总是假设每一次临界区操作会产生冲突&#xff0c;因此&#xff0c;必须对每次操作都小心翼翼。如果多个线程同时访问临界区资源&#xff0c;就宁可牺牲性…

深入理解CAS算法原理

转载自 深入理解CAS算法原理 1、什么是CAS&#xff1f; CAS&#xff1a;Compare and Swap&#xff0c;即比较再交换。 jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证…

CAS操作原理

1、什么是CAS&#xff1f; CAS&#xff1a;Compare and Swap&#xff0c;即比较再交换。 jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的&#xff0c;这是一…

CAS原理

一、CAS 1.1 CAS概述和作用 CAS的全称是&#xff1a; Compare And Swap(比较相同再交换)。是现代CPU广泛支持的一种对内存中的共享数据进行操作的一种特殊指令。 CAS的作用&#xff1a;CAS可以将比较和交换转换为原子操作&#xff0c;这个原子操作直接由CPU保证。 CAS可以保证…

CAS算法详解

CAS算法 1、CAS概念&#xff1a; CAS是CompareAndSwap的缩写&#xff0c;中文意思是&#xff1a;比较并替换。当要进行CAS操作时&#xff0c;先比较内存地址和原来预期的 地址比较&#xff0c;如果相同&#xff0c;表示这块内存地址没有被修改&#xff0c;可以用新地址替换&…

CAS的原理和使用

CAS 文章目录 CAS一、学习CAS首先了解原子类&#xff1f;1. 何为原子类 二、 CAS是什么1. CAS是什么2. CAS原理3. 使用CAS实例代码4. CAS属于硬件级别保证5. 源码分析 三、CAS底层原理&#xff1f;如果知道&#xff0c;谈谈你对UnSafe的理解1. UnSafe2. 我们知道i线程不安全的&…

对cas算法的理解

cas算法主要关心3个值&#xff1a;内存值V&#xff0c;预期值A&#xff0c;要更新的新值B 如下图所示&#xff1a; 注&#xff1a;t1&#xff0c;t2线程是同时更新同一变量56的值 因为t1和t2线程都同时去访问同一变量56&#xff0c;所以他们会把主内存的值完全拷贝一份到自己…

CAS原理分析

CAS的英文为Compare and Swap 翻译为比较并交换。 CAS加volatile关键字是实现并发包的基石。没有CAS就不会有并发包&#xff0c;synchronized是一种独占锁、悲观锁&#xff0c;java.util.concurrent中借助了CAS指令实现了一种区别于synchronized的一种乐观锁。 什么是乐观锁与…

CAS详解

一、CAS概念 1.1 CAS是什么 Compare And Swap 比较并交换 1. 如果线程的期望值跟物理内存的真实值一样&#xff0c;就更新值到物理内存当中&#xff0c;并返回true 2. 如果线程的期望值跟物理内存的真实值不一样&#xff0c;返回false&#xff0c;那么本次修改失败&#xf…

CAS算法的理解及应用

应用 原子操作类&#xff0c;例如AtomicInteger&#xff0c;AtomicBoolean …适用于并发量较小&#xff0c;多cpu情况下&#xff1b; Java中有许多线程安全类&#xff0c;比如线程安全的集合类。从Java5开始&#xff0c;在java.util.concurrent包下提供了大量支持高效并发访问…

解析CAS算法原理

解析CAS算法原理 什么是CAS&#xff1f;CAS原理概念实现形式底层原理 案例CAS的缺点ABA问题ABA问题如何产生的&#xff1f;原子的引用时间戳原子的引用利用AtomicStampedReference解决ABA问题案例 什么是CAS&#xff1f; CAS&#xff0c;全称Compare And Swap&#xff0c;顾名…

深入解析CAS算法原理

目录 一、CAS的基本概念二、CAS算法理解三、CAS开销四、CAS算法在JDK中的应用 一、CAS的基本概念 CAS&#xff1a;Compare and Swap&#xff0c;即比较再交换&#xff0c;是一种硬件对并发的支持&#xff0c;针对多处理器操作而设计的处理器中的一种特殊指令&#xff0c;用于管…

CAS算法实现

https://blog.csdn.net/bluetjs/article/details/52261490?locationNum15&fps1 1.什么是cas&#xff1f; cas是一种无锁算法&#xff08;非阻塞算法&#xff1a;一个线程的失败或者挂起不应该影响其他线程的失败或者&#xff09;&#xff0c;是compare and swap的缩写&am…

修改Idea的jdk版本

概述 idea很多地方都设置了jdk版本&#xff0c;不同模块的jdk版本也可能不一样&#xff0c;下面整理下涉及jdk或者jre版本的几个地方。 方法一 File - Settings - Build, Execution, Deployment - Build Tools - Maven - Importing 方法二 File - Settings - Build, Exec…

Linux切换jdk版本

开发常识 命令行输入下列命令&#xff0c;然后输入 1 、2、3 选择你想要的 jdk 版本&#xff1a; sudo update-alternatives --config java选择完之后查看 jdk 版本&#xff1a; java -version

如何查看JDK版本信息

如何查看JDK版本号 一、前言二、 Windows的dos窗口 一、前言 在下载某些工具时需要知道自己电脑安装的JDK版本号&#xff0c;这里介绍了一种可以看自己JDK版本号的方法。 二、 Windows的dos窗口 1.电脑WindowsR键&#xff0c;打开命令行窗口   2.在命令行里面输入cmd;   3…

mac安装多个JDK版本

因对不同版本的JDK需求&#xff0c;有时候需要安装多个切换使用&#xff0c;这里我为Mac安装了多个JDK。在已有JDK8的基础上又安装了JDK11。 1、国内镜像下载JDK11&#xff0c;下载地址&#xff1a;https://repo.huaweicloud.com/java/jdk/11.0.29/jdk-11.0.2_osx-x64_bin.dmg…

更改JDK版本

1、更改环境变量&#xff1a;JAVA_HOME的路径&#xff08;此路径下要有bin目录&#xff09; 换成你要用的java的版本所在的路径 2、找到系统变量path下的java路径&#xff0c;将此路径下的三个文件全部删掉 3、打开regedit 修改数据数值即可&#xff0c;如下图切换成功

查看javajdk版本

查看当前电脑的Java/JDK版本的方法 1.winR 打开运行窗口&#xff0c;输入 cmd 2.在控制台中输入java --version或者java -version&#xff0c;即可查看Java版本号 Java所有版本 版本号 发布日期 JDK Version 1.0 1996-01-23 Oak(橡树) JDK Version 1.1 1997-02-19 …

如何更换jdk版本

如何更换jdk版本 因为很多时候需要切换jdk版本。也是走了很多弯路才弄好。此次演示的是将1.7 的版本更换成1.8 的。下面是详细步骤先查看当前版本&#xff0c;输入cmd 打开命令提示符后输入 java -version 即可 可以将1.8 的jdk 于1.7 的jdk 安装在同一个目录下&#xff0c;会…