对CAS的理解

简介: 对CAS的理解

CAS的概念(compare and swap):比较并交换

8891b907eb06e444ed453ebea6afa53f.png

我们首先要明白,自旋是一个纯用户态的操作,本身并没有进行加锁,所执行的代码,是在并发环境下执行的,没有锁。

我们举一个例子来说明自旋加CAS的作用:


121f2075948a065c1371d309d0377ee9.png

9a59e2be2c04aa9f918c4405b6bf4439.png

我们画一个时间图来接着证明:

d8e30d5d2cccd88a39380f32ac689290.png

线程中的Load和CAS的load并不一样,线程中的Load是获取预期值,而CAS中的load是在主内存中获取值,与预期值进行比较,两者作用并不相同。我们发现CAS并不是一个操作,首先要进行预期值和主内存中的值的比较,如果相同再进行下一步的操作,不相同则重新自旋+CAS,伪代码如下,按理说应该对应着许多条cpu指令,但是事实上它只对应着一条cpu指令(cmpxchg),一条指令可以完成所有操作,这条指令对应着系统的一个API,这个API有三个参数:地址值,预期值和要修改的值,但是我们必须要明白的是CAS的实现是通过cpu硬件提供的lock机制保证其原子性,简而言之就是因为硬件层面给予了支持,软件层面才能达到。

1cc607f18944a2709ba8a505342be1da.png

注意:CAS最重要的是判断我们第一次获取到的预期值和主内存中的值是否一致,也就是说数据是否在我们获取完预期值之后被其他线程修改过,没有修改过我们在此基础上进行的修改和写回操作是线程安全的,如果被修改过,此时我们再进行的修改和写回操作可能覆盖之前修改的值,这是线程不安全的。

CAS的两个应用:

①实现自旋锁:

伪代码如下:

9f3edcc02a5e5676e0fbb418bcd8ba17.png

②实现原子类

我们关于原子类的代码如下:

public class demo1001 {

   public static void main(String[] args) throws InterruptedException {

       //创建基于CAS的原子类

       AtomicInteger atomicInteger = new AtomicInteger();

       //创建两个线程实现自增操作

        Thread t1 =new Thread(()->{

            for (int i = 0; i <50000 ; i++) {

                atomicInteger.getAndIncrement();

            }

                });

        Thread t2 =new Thread(()->{

            for (int i = 0; i <50000 ; i++) {

                atomicInteger.getAndIncrement();

            }

                });

        //两个线程均开始执行

       t1.start();

       t2.start();

       //等待两个线程均执行结束

       t1.join();

       t2.join();

       System.out.println(atomicInteger);

   }

}

在这段代码中,我们并没有使用synchronized进行上锁,但是结果仍然是正确8f6ee58ad397d00ae2d6c74000853e11.png

我们查看其源码:


14f7ad08fce08236aa40739f2a3464f1.png

0cd5683d6bc007885fc5dc1ecf582547.png

关于CAS中的ABA问题:

ABA 的问题:

假设存在两个线程 t1 和 t2. 有一个共享变量 num, 初始值为 A.

接下来, 线程 t1 想使用 CAS 把 num 值改成 Z, 那么就需要

先读取 num 的值, 记录到 oldNum 变量中.

使用 CAS 判定当前 num 的值是否为 A, 如果为 A, 就修改成 Z.

但是, 在 t1 执行这两个操作之间, t2 线程可能把 num 的值从 A 改成了 B, 又从 B 改成了 A线程 t1 的 CAS 是期望 num 不变就修改. 但是 num 的值已经被 t2 给改了. 只不过又改成 A 了. 这个时候 t1是否要更新值为Z呢?

那在实际生活中我们举这样一个例子:

52b5053b477c315dec342ac0a6fa4da9.png

虽然从值的大小来看虽然是一样的,但是从操作过程和逻辑上来说有着很大的区别,可以说是两个完全不同的结果,那么我们又该如何解决这个ABA问题呢?

答案很简单,增加一个版本号,当有人对这个数据操作之后,该数据的版本号加1,虽然结果一致,但是我们可以通过版本号来判断这个结果是否是我们期望的结果

c9beafd0d707ed46e498e3d8f215a68a.png


相关文章
|
5天前
|
云安全 人工智能 安全
AI被攻击怎么办?
阿里云提供 AI 全栈安全能力,其中对网络攻击的主动识别、智能阻断与快速响应构成其核心防线,依托原生安全防护为客户筑牢免疫屏障。
|
15天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
9天前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
600 214
|
存储 人工智能 监控
从代码生成到自主决策:打造一个Coding驱动的“自我编程”Agent
本文介绍了一种基于LLM的“自我编程”Agent系统,通过代码驱动实现复杂逻辑。该Agent以Python为执行引擎,结合Py4j实现Java与Python交互,支持多工具调用、记忆分层与上下文工程,具备感知、认知、表达、自我评估等能力模块,目标是打造可进化的“1.5线”智能助手。
836 61
|
7天前
|
人工智能 移动开发 自然语言处理
2025最新HTML静态网页制作工具推荐:10款免费在线生成器小白也能5分钟上手
晓猛团队精选2025年10款真正免费、无需编程的在线HTML建站工具,涵盖AI生成、拖拽编辑、设计稿转代码等多种类型,均支持浏览器直接使用、快速出图与文件导出,特别适合零基础用户快速搭建个人网站、落地页或企业官网。
1234 157
|
4天前
|
编解码 Linux 数据安全/隐私保护
教程分享免费视频压缩软件,免费视频压缩,视频压缩免费,附压缩方法及学习教程
教程分享免费视频压缩软件,免费视频压缩,视频压缩免费,附压缩方法及学习教程
236 138
|
7天前
|
存储 安全 固态存储
四款WIN PE工具,都可以实现U盘安装教程
Windows PE是基于NT内核的轻量系统,用于系统安装、分区管理及故障修复。本文推荐多款PE制作工具,支持U盘启动,兼容UEFI/Legacy模式,具备备份还原、驱动识别等功能,操作简便,适合新旧电脑维护使用。
517 109