CAS 是什么?

article/2025/9/29 16:08:33

CAS又称 自旋锁、无锁,是一种乐观锁 

 

 

  1. compare and swap 的缩写 意为: 比较并交换 , 实现并发算法的常用技术 , 就是说我不用加锁 , 也能保证 ( 加锁会影响效率,可以考虑使用原子操作类 )  原子性 , 当多个线程尝试使用 CAS 同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试 , 因此可以知道 , CAS只会允许一个线程的执行成功
  2. CAS 包括三个操作数 - 内存位置 , 预期原值以及更新值
    1. 执行 CAS 操作的时候,将内存位置的值与预期原值比较
      1. 如果相匹配 , 那么处理器会自动的将该位置更新为新值
      2. 如果不匹配 , 处理器不做任何操作 , 多个线程同时执行 CAS 的操作只有一个成功

例如下面的 AtomicInteger 等 原子类 就是基于 CAS 实现的

    

操作的过程图解:

  1. CAS有三个操作数,位置内存值V , 旧的预期值A , 要修改的更新值B
  2. 当且仅当旧的预期值A 和内存值V相同时 , 将内存值V修改为B , 否则什么都不做或重来

 

 AtomicInteger 执行过程源码:

AtomicInteger atomicInteger=new AtomicInteger();public void addAtomic(){atomicInteger.getAndIncrement();}// getAndIncrement方法 this是当前AtomicIntegr对象// valueOffset是内存偏移量/值// 1为自增量// Unsafe类的getAndAddInt方法,该Unsafe类是在jdk里的rt.jar包public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);}public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {//var1对象里的var2这个内存偏移量的值 var5 = this.getIntVolatile(var1, var2);         //var1 AtomicInteger 对象本身//var2 该对象值得引用地址,内存地址偏移量//var4 需要变动的数量 +1//var5 是用var1 var2 找出的主内存中真实的值//用该 对象当前的值与var5比较//如果相同,进行var5+var4并且返回true//如果不同,继续从主内存中取值然后 再比较,直到更新完成} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));return var5;}

        创建一个原子类对象 ( 默认初始化值为0 ) , 也可以传入定值 , 当我们使用CAS方法时 , 传入一个预期值 , 一个修改值 , 仅当预期值和当前对象 valueOffset的内存偏移量的值相同 , 就可以修改成功 , 前提是没有被其他的线程抢先一步进行比较并交换 , 否则就要继续读取最新的修改值 ( 变量可以使用 volatile关键字解决可见性问题 , 就是说 : 一个线程对共享变量的修改,能够及时的被其他线程看到 , 立刻同步最新数值 ) , 再继续的进行比较并交换这一操作 , 直到修改成功..... 这是比较并交换的源代码 : native为本地方法 , 底层用C 实现对操作系统的访问和操作 (Java不可以直接访问) 

此代码以及执行流程如下 :

 

while ( ! this.compareAndSwapInt ( var1, var2, var5, var5 + var4 ) ) 的执行流程:

  • 当两个线程 A , B 同时执行 AtomicInteger 中的自增方法( getAndAddlnt ) 时 , 假如 AtomicInteger 中主内存的值是10
    • 线程 A 调用 getlIntVolatile (var1, var2) 获取一份原始内存值(最新值)10 , 开始要操作了
    • 线程 B 调用 getlIntVolatile (var1, var2) 也获取一份原始内存值(最新值)10 , 开始要操作了
    • 线程 A 抢夺的速度很快, 调用 compareAndSwaplnt 方法 ,  预期值和原始值相同都是10 , 比较并修改为11
    • 线程 B 这时调用 compareAndSwaplnt 方法 , 发现自己的期望值是10,但是内存中真正的原始值被修改为11了,被其他线程修改了 , 这时线程A就修改失败 , 重新读取内存中的新值 value (volatile关键字作用: 及时的被其他线程看到最新的 value值 , 共享变量值的修改 )
    • 线程 B 继续进行调用 compareAndSwaplnt 方法 , 比较并修改

注意 : 这时线程B 还不一定就能修改成功 , 有可能还有其它线程抢夺的速度比它快 , 很快的将期望值 var5 进行了修改 , 线程B比较发现和期望值不匹配 , 因此线程B可能继续下去 , 直到比较成功 , 返回 ture 即可

为什么原子类可以不加 synchronized 实现原子性 ?


何为原子性:原子就是最小的单位 , 不可分割的 , 就是指一个操作是不可中断的。即使是多个线程一起执行的时候 ,一个线程的操作一旦开始,执行的过程中不允许被中断 , 也就是说不会被其他线程干扰 ,  直到执行完毕 , 不会造成数据不一致的问题 , 因此原子类使用 CAS 保证了并发情况下线程的安全性

 

1. Unsafe 这个类是Java底层的一个类 , 是 CAS 的核心类 , 相当于是一个后门 , 它存在于 sun.misc 包中 , Unsafe 类中的所有的方法都是被 native 关键字修饰的 , 被 native 修饰的方法为本地方法 , 底层是用 C 实现对操作系统的访问和操作 , 就比如调用 UnSafe 类中的 CAS 方法 , 它是通过操作系统的汇编指令来实现操作内存数据的 , 因为Java中 CAS 操作的执行依赖于Unsafe 类的方法

2. Unsafe 通过 对象的 valueOffset 内存偏移地址获取原始内存值 , 用当前工作内存值 (var1,var2) 和期望值 (var5) 进行比较判断是否能替换 , 一旦修改了 , 其他的线程一比较发现工作内存的值和期望值不一样 , 所以就无法操作了 , 只能继续获取新值 (getIntVolatile) , 继续比较 , 这样就保证了一次只能有一个线程在执行并且执行成功 , 就算不加锁 , 其他的线程也是进不来的 , 就无法操作 , 因此我们说 : 原子类可以不加 synchronized 就实现了原子性,保证了线程的安全

 

3. 被 volatile 修饰的变量 , 保证了线程的可见性 , 一旦被修改 , 就能及时的将数据反馈给其他线程 , 以供其他线程获取最新的值

CAS 的缺点


  1. CAS 它是一条 CPU并发原语 , 当执行 getAndAddInt 方法的时候 , 里面有一个do while 方法 , 如果CAS失败 ,会一直进行尝试 比较 , 假如有一百万个线程 , 如果 CAS 长时间一直不成功 , 这么多的线程会直接给CPU打满 , CPU 的开销变大
  2. 当对一个共享变量执行操作时 , 我们可以使用循环 CAS 的方式保证原子操作 , 对多个共享变量操作时,循环CAS就无法保证操作的原子性 , 这个时候就可以用锁来保证原子性。
  3. ABA 问题 :
    1. 线程A从主内存中拿了一份值 , 假如是10 , 它在自己的工作空间中打算进行修改了 (还没修改)
    2. 这时线程B抢占了线程A , 它从主内存中将10取出来了, 它给修改成了22 , 放回主内存中了 , 但是呢 ,它感觉修改的不满意 , 又去主内存把那个22又取出来了 , 又给改成了10 , 然后走了
    3. 这时线程A 去进行比较并交换 , 发现工作内存值和主内存值(期望值)是一样的都是10 , 就成功修改了, 但是 ! 注意 ! 线程A并不知道这个值中途被其他线程修改了 ! ! !

解决方案:用 AtomicStampedReference 的时间戳版本号解决 ABA 问题 ,进行版本号的比较 , 每次变动时 , 都会产生一个版本号 

 

 


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

相关文章

什么是CAS

文章目录 一、CAS是什么二、CAS 可以解决什么问题三、CAS实现原子操作的问题 一、CAS是什么 CAS的全称为compare and swap 或者compare and exchange,意思为比较和交换。CAS流程如下: 假设我们有一个共享变量i,初始值为0。我们现在要对i进行加1的操作…

metasploit图形化工具 Armitage

Metasploit默认使用PostgreSQL存储渗透测试所需的数据表,所以在启动Armitage之前需要首先启动PostgreSQL服务和Metasploit服务,然后再启动armitage,弹出对话框询问是否连接Metasploit的RPC信道,依次选择“connect”、“是”选项。…

ARM..

一 关于arm 1 arm的三种含义 (1) 一个公司的名称 Advanced RISC Machine (2) 一类处理器的统称 (3) 一种技术的名称 (RISC) ARM是以一家设计处理器的公司,这家公司设计的处理器统称为ARM,它们使用的指令集是RISC(精简指…

01-Introducing the Arm architecture

快速链接: . 👉👉👉 个人博客笔记导读目录(全部) 👈👈👈 付费专栏-付费课程 【购买须知】:【精选】ARMv8/ARMv9架构入门到精通-[目录] 👈👈👈目录 1、Overview2、About the Arm architecture3、架构(architecture)到底是什么意思呢

傻瓜式渗透Armitage的使用

目录 Armitage的基本介绍 安装 1 启动Armitage 1、Armitage启动前初始化: 2、Armitage启动的三种方法: 2 使用Armitage生成被控端和主控端 1、Armitage的工作界面: (1)区域1: (2&#…

Kali Linux Armitage生成被控端和主控端

目录 说明使用 Armitage生成被控端和主控端 说明 按照《Kali Linux2 网络渗透测试实践指南 第二版 》第八章操作 仅供学习讨论使用,请勿进行非法操作 使用 Armitage生成被控端和主控端 选中“payload”, 然后选择“windows” ➡️“meterpreter”&…

[architecture]-arm exclusive机制介绍

关键词:spinlock,原子操作,独占访问,exclusive,inclusive,mutex,Semaphore,互斥,同步,同步原语 快速链接: . 👉👉👉 个人博客笔记导读目录(全部) 👈👈👈 付费专栏-付费课程 【购买须知】: 【精选】ARMv8/…

使用Armitage进行渗透测试与键盘记录

0x00:Armitage是一款基于GUI开发的图形化渗透工具,对于渗透测试而言能够快速了解网络的拓扑以及主机状态,其功能丰富,是每一位渗透测试者的必备武器;今天我就来演示如何在Armitage下入侵纯在漏洞的XP系统,废…

在2022年的kali linux上面安装armitage

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 在2022年的kali linux上面安装armitage 前言一、armitage是什么?二、安装步骤1.官网下载2.build安装3.配置数据库 总结 前言 提示:在2022年的kali li…

ARMv8 architecture里的Memory aborts

在AArch64 Virtual Memory System Architecture中,有以下几种机制会导致PE在访问memory失败时产生exceptions。 Debug exception: An exception caused by the debug configuration.Alignment fault: An Alignment fault is generated if the address used for a m…

Armitage图形化前端

开源免费图形前端 ● 作者自称是众多不会使用metasploit的安全专家之一(命令行) ● MSF基于命令行,缺少直观的GUI图形用户接口 Armitage只是调用MSF的漏洞利用能力 ● Armitage的每一个GUI操作都可以对应MSF中的一条命令 红队团队合作模拟…

Kali Linux 使用Armitage

目录 说明安装扫描网络Quick Scan (OS detect)输入网段扫描结果 图形化ms17_010先扫描 auxiliary再攻击被渗透图形化metaspliotMeterpreter 5类任务:计算系统密码的hash值 Browser filesLog Keystrokes 写在最后 Armitage是一款用Java为Metasploit编写的图形化操作界…

【Arm架构】什么是Arm?

1 Arm architecture Arm 架构是世界上最流行的处理器架构之一。每年有数十亿台基于 Arm 的设备出货。 A-Profile (Applications) R-Profile (Real-Time) M-Profile (Microcontroller) 高性能场景 实时系统 小型,高能效设备 用于运行复杂的操作系统&#xff0…

「Arm Arch」 初识 Arm

本文源自《书香度年华》「ARM 架构专栏」,是一系列由浅入深、循序渐进的文章,文章之间有一定的前后关联性,所以按顺序阅读,建议收藏专栏。 目录 前言 一、架构概述 1.1 冯诺依曼架构 1.2 哈佛架构 1.3 Arm 架构 二、架构图谱…

Armitage的介绍和使用

目录 1.1Armitage的介绍与原理 1.1.2 Armitage的主要功能包括: 1.2 启动Armitage 1.2.1 Armitage启动的三种方法: 1.2.2 Armitage启动前初始化: 1.3 使用Armitage生成被控端和主控端 1.3.1 Armitage的工作界面: 1.3.2 使用…

ARM 架构是什么?

ARM(Advanced RISC Machines)架构是一种处理器架构,它是一种精简指令集计算机(RISC)架构。ARM架构最初由ARM Holdings(现在是SoftBank Group的子公司)开发,并在1980年代末和1990年代…

Armitage的使用

一.简介 Armitage是一个攻击管理工具,它以图形化方式实现了Metasploit框架的自动化攻击。Armitage采用Java构建,拥有跨平台特性。 二.使用 (一)基本原理 1.入门 1.1开启Armitage 在命令行输入armitage命令会弹出如下对话框&…

黑客工具Armitage

Armitage介绍: Armitage是一款Java写的Metasploit图形界面化的攻击软件,可以用它结合 Metasploit中已知的exploit来针对主机存在的漏洞自动化攻击。通过命令行的方式使用Metasploit难度较高,需要记忆的命令过多,而Armitage完美的…

Armitage的介绍与使用

目录 1.1 Armitage的介绍与原理1.1.1 Armitage主要利用什么漏洞?为什么会出现这种漏洞?攻击怎么实现? 1.2 启动Armitage1.2.1 Armitage启动的三种方法:1.2.2 Armitage启动前初始化: 1.3 使用Armitage生成被控端和主控端…

Armitage之——网络扫描以及主机管理

转载请注明出处:https://blog.csdn.net/l1028386804/article/details/86676136 继续上一篇《Armitage之——基本原理》 Armitage中使用独立的Hosts选项卡来实现主机的管理操作和主机的扫描操作。可以单击导航栏上的Hosts按钮选项,然后选中下拉菜单上的…