CAS概念、性质、优缺点 | 乐观锁、悲观锁是什么?

news2024/9/17 8:28:57

前言:

       今天在深入了解HashMap时,看到这句话:“concurrentHashMap,在 JDK 1.7 中采用 分段锁的方式;JDK 1.8 中直接采用了CAS(无锁算法)+ synchronized。”

       哦~~这个CAS好像之前接触过,又不记得了~遂重新复习总结一下


目录

 一、CAS基础知识

1.CAS概念:

2.CAS 所需3个参数:

3.CAS 操作过程:

4.举例子说明CAS

二、CAS性质

1.什么是乐观锁?什么是悲观锁?

2.CAS 实现的原子性

3.CAS 的优点

4.CAS 的缺点

5.CAS的实际应用场景: 

三、Java编程模实现CAS操作

1.例子A:

2.例子B(存在自旋现象)


 一、CAS基础知识

1.CAS概念:

        CAS(Compare-And-Swap)是一种 乐观锁 机制,在并发编程中被广泛应用。它的核心思想是让线程假设在执行某个操作时不会发生冲突,因此尝试直接进行操作。如果没有其他线程同时修改同一个数据,操作就能顺利完成;如果发生冲突,线程会检测到这一点,并再次尝试,直到操作成功为止。

2.CAS 所需3个参数:

  1. 内存位置(V):要操作的变量的内存地址。
  2. 期望值(E):执行操作时,线程期望变量的当前值。如果该值与实际值一致,则认为没有其他线程修改过该变量。
  3. 新值(N):如果期望值与变量当前值相等,则将变量更新为新值。

3.CAS 操作过程:

  1. 线程读取内存位置 V 的值,并比较它是否等于期望值 E
  2. 如果 V == E,则将 V 设置为 N,操作成功。
  3. 如果 V != E,说明在此期间已经有其他线程修改了该变量,操作失败,线程会进行重试。

4.举例子说明CAS

a:现实生活中的例子

- 我跟小明说:空调开太冷啦,你去把空调从26度,调节到28度。

- 小明是一个只会CAS的呆瓜,它接收到的指令是:V:当前空调上显示的温度,E:26,N:28

- 此时一只小猫不小心按到遥控器,把空调设置成了27度!

- 小明刚想调节温度时发现:此时V=27,不等于E的26,呆瓜小明该次操作失败 


二、CAS性质

1.什么是乐观锁?什么是悲观锁?

假如这两个锁会说人话:

乐观锁:我超乐观的!我觉得我要修改的资源肯定没有人线程用嘻嘻,那我就直接修改啰~如果提交时发现有人把我的改了,我就再改一遍(重试)

悲观锁:呜呜呜一定会有其他线程跟我一起要修改这个资源QAQ,我得先把房门锁上(加锁),不让别的线程进来,没有线程可以影响我,等我改完再把门敞开。

乐观锁、悲观锁概念:

乐观锁:假设在大多数情况下,多个线程不会发生冲突,因此允许多个线程并发地读取和修改共享资源在操作完成时,检查是否有其他线程修改了数据。如果发现冲突,乐观锁会重试操作,直到操作成功为止。CAS操作就是乐观锁的常见实现。

悲观锁:假设在并发环境中冲突会经常发生,因此在访问共享资源时,线程会采取加锁的方式来确保数据的一致性。在一个线程对资源加锁后,其他线程需要等待锁被释放才能访问该资源。

2.CAS 实现的原子性

         CAS 的原子性通常由硬件支持的指令集来保障。例如,在 x86 体系结构中,cmpxchg 指令就是实现 CAS 的底层支持。该指令可以确保比较和交换操作是一个不可分割的原子操作,从而防止多个线程在同一时刻同时对共享变量进行修改。

3.CAS 的优点

  1. 无锁化:CAS 不依赖于锁,不会造成线程阻塞。相比传统的加锁机制,避免了线程上下文切换的开销,提高了系统的并发性能。

  2. 高效:在大多数情况下,冲突发生的概率较低,因此 CAS 操作可以直接完成修改操作。即使冲突发生,由于只需要重试,操作成本也相对较小。

  3. 非阻塞:当一个线程在执行 CAS 操作时,即使另一个线程同时进行相同操作,它们不会互相阻塞,反而会竞争性地更新数据。这种无锁机制适用于高并发场景。

4.CAS 的缺点

  1. ABA 问题:CAS 只能检测到变量的值是否发生变化,但无法感知值的多次变更。例如,变量从 A 变为 B,再从 B 变回 A,CAS 认为数据没有变化,因此会认为操作是安全的。这种情况就是 ABA 问题

    解决方案:可以通过引入 版本号 来避免 ABA 问题。每次变量修改时,除了更新变量的值,还更新一个版本号。如果版本号发生了变化,即使数据看似没有变,CAS 仍然能检测到。Java 中的 AtomicStampedReference 类就提供了这种机制。

  2. 自旋开销:如果 CAS 操作失败,线程通常会采用自旋重试的方式来尝试更新。虽然 CAS 不会阻塞线程,但在高并发的环境下,多个线程同时修改同一变量可能导致频繁的 CAS 失败,增加了 CPU 的开销。

  3. 只能保证单个变量的原子操作:CAS 只能对一个共享变量进行原子操作,如果需要同时更新多个变量,CAS 无法保证多个变量之间的操作是原子的。这种情况下,需要使用传统的锁机制来解决。

5.CAS的实际应用场景 

  1. 高并发计数器:像AtomicIntegerAtomicLong等类都是基于CAS实现的,它们广泛应用于高并发环境中的计数器操作,例如统计请求数、处理任务数等。

  2. 并发队列ConcurrentLinkedQueue是一个无锁的并发队列,内部通过CAS实现队列的入队和出队操作,保证高效地处理高并发下的元素操作。

  3. 多线程下的资源状态更新:CAS可以用于实现无锁的状态更新,比如某些多线程应用中常见的标志位更新或任务状态切换。

  4. 线程池中的任务处理:在Java线程池的实现中,很多操作是基于CAS进行的,如任务计数、线程状态的管理等,确保在高并发下的高效调度。


三、Java编程模实现CAS操作

1.例子A:

还是用上面小明开空调的例子,我们来写一个代码:

import java.util.concurrent.atomic.AtomicInteger;

public class AirConditionerCAS {
    // 使用 AtomicInteger 来模拟共享的温度变量
    private static AtomicInteger temperature = new AtomicInteger(26);

    public static void main(String[] args) {
        // 小猫不小心按到遥控器,把温度设成了 27 度
        temperature.set(27);

        // 小明尝试将温度从 26 度调整到 28 度
        int expectedValue = 26;
        int newValue = 28;

        // 小明进行 CAS 操作,只有当当前值等于 26 时才会更新为 28
        boolean success = temperature.compareAndSet(expectedValue, newValue);

        if (success) {
            System.out.println("温度成功调整为: " + temperature.get() + " 度");
        } else {
            System.out.println("调节失败,当前温度是: " + temperature.get() + " 度");
        }
    }
}

解释代码:

  1. AtomicInteger temperature:这是一个 AtomicInteger 类型,用来模拟共享的整数变量。AtomicInteger 内部使用 CAS 操作来保证线程安全。

  2. compareAndSet(expectedValue, newValue):这个方法实现了 CAS 操作。它会检查当前的 temperature 是否等于 expectedValue,如果相等,则更新为 newValue;如果不相等,则不做任何修改,并返回 false。

运行结果:

如我们所料。

compareAndSet的源码我们看到: 

该方法是通过调用底层的方法实现的。注意这个例子中是一个最底层的CAS的原子操作,不存在自旋现象。下面举一个会存在自旋现象的。

2.例子B(存在自旋现象)

import java.util.concurrent.atomic.AtomicInteger;

public class CASExample {
    // 使用AtomicInteger来实现线程安全的计数器
    private static AtomicInteger counter = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        // 创建100个线程,每个线程对counter进行1000次递增操作
        Thread[] threads = new Thread[100];

        for (int i = 0; i < 100; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    // 递增操作
                    counter.incrementAndGet();  // 实现CAS自旋锁
                }
            });
            threads[i].start();
        }

        // 等待所有线程执行完
        for (Thread t : threads) {
            t.join();
        }

        // 最终counter的值应该是100000
        System.out.println("Final counter value: " + counter.get());
    }
}

运行结果: 

成功实现多线程并发增加变量。

关于counter.incrementAndGet()方法的解释:

本质还是通过while循环,不断尝试调用底层的原子方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2116745.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VSCode拉取远程项目

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

2024年测评7款最佳AI论文修改润色平台

在2024年&#xff0c;AI论文修改润色平台的测评和推荐成为学术界和研究者们关注的热点。本文将详细评测并推荐7款最佳AI论文修改润色平台&#xff0c;包括千笔-AIPassPaper&#xff0c;并结合我搜索到的资料进行分析。 一、千笔-AIPassPaper 千笔-AIPassPaper是一款集论文大纲…

芯旺微,车规级32位MCU KF32A芯片简介

文章目录 1. 产品功能特点2. 行业应用3. 开发环境(IDE)4. 开发资源5. KungFu 内核参考1. 产品功能特点 2. 行业应用 汽车照明汽车车窗控制汽车空调面板汽车控制器3. 开发环境(IDE)

营养方案调整执行流程 第十篇

追踪调整方案 疾病诊断≠营养诊断 出健康管理建议应考虑地域习惯等特点&#xff0c;因人而异

HarmonyOS应用开发( Beta5.0)一杯冰美式的时间“拿捏Grid组件”

常见情形 在很多手机商城的页面中会出现类似网格状一样的情况&#xff0c;例如&#xff1a; 京东 ​这里呢是采用Grid组件中的控制滚动,里面的rowsTemplate属性为一行且不对列的行数属性进行操作&#xff0c;这样的话就可以控制水平滑动了。 2.淘宝 ​ 这里就是极其简单的2*…

Google Play结算防掉单方案

我们公司的产品主要是出海产品,使用的是Google Play支付,但是在上线以后,经常有客诉,说支付以后,权益没有到账,于是对整个Google支付体系做了研究了一下。 我们的整个支付流程图大概如下: 其中后端参考的文档地址为: https://developers.google.com/android-publishe…

Springboot中基于X509完成SSL检验的原理与实践

前言 各位对HTTPS不陌生吧&#xff1f;几乎涉及安全的领域&#xff0c;均要求通过HTTPS协议进行数据传输。而在传输过程中&#xff0c;又涉及到了SSL证书的使用。既然提到了SSL证书&#xff0c;那咱们先了解了解什么是SSL证书&#xff1a; SSL证书通过在客户端浏览器和Web服务…

生信代码入门:从零开始掌握生物信息学编程技能

少走弯路,高效分析;了解生信云,访问 【生信圆桌x生信专用云服务器】 : www.tebteb.cc 介绍 生物信息学是一个高度跨学科的领域&#xff0c;结合了生物学、计算机科学和统计学。随着高通量测序技术的发展&#xff0c;海量的生物数据需要通过编程来进行处理和分析。因此&#x…

如何使用云服务器AutoDL进行炼丹

如何使用云服务器进行炼丹 文章目录 如何使用云服务器进行炼丹1、选择平台2、学生认证3、租用新实例1&#xff09;创建实例2&#xff09;选择镜像3&#xff09;注意事项 4、文件传输1&#xff09;下载XFTP&#xff0c;用来传输文件2&#xff09;XFTP连接 5、pycharm远程连接1&a…

【Github项目推荐】DataLoom

项目推荐 - DataLoom 项目背景 在数据驱动的时代&#xff0c;越来越多的企业和个人用户需要从复杂的数据中提取出高价值的信息。然而&#xff0c;传统的数据处理和分析流程复杂且耗时&#xff0c;需要技术人员的深度参与。那么&#xff0c;有没有一种工具能够简化这一过程&am…

Linux:归档及压缩

tar命令 • tar 集成备份工具 – -c&#xff1a;创建归档 – -x&#xff1a;释放归档 – -f&#xff1a;指定归档文件名称,必须在所有选项的最后 – -z、-j、-J&#xff1a;调用 .gz、.bz2、.xz 格式工具进行处理 – -t&#xff1a;显示归档中的文件清单 – -C&#xff1a;指定…

十年多空局

我收到的有关大洋彼岸的推送&#xff1a; 微信和头条上的长者们&#xff0c; 讲着他们小时候没有的GPU和生物技术&#xff0c; 看多 B站上的年轻人&#xff0c; 谈着他们一知半解的制度设计和宏观经济&#xff0c; 看空 十年尺度的看空与看多

githup怎么上传自己的项目

&#xff08;1&#xff09;首先进入自己要上传项目的文件夹中&#xff0c;然后点击Open git Bash here. &#xff08;2&#xff09;然后进入下面界面&#xff0c;输入git init &#xff08;3&#xff09;然后就会生成一个.git的文件夹 &#xff08;4&#xff09;输入git add *…

如何处理软件卸载不干净的情况?

如何处理软件卸载不干净的情况&#xff1f; 一、清理注册表 下载CCleaner&#xff0c;下载之后&#xff0c;点击settings&#xff0c;将语言改为中文。 点击注册表&#xff0c;点击扫描问题-修复选定的问题&#xff0c;最好将之前的注册表完整备份。 反复这一过程&#xff0c…

Spring Boot集成Tess4J实现OCR

1.什么是Tess4j&#xff1f; Tesseract是一个开源的光学字符识别&#xff08;OCR&#xff09;引擎&#xff0c;它可以将图像中的文字转换为计算机可读的文本。支持多种语言和书面语言&#xff0c;并且可以在命令行中执行。它是一个流行的开源OCR工具&#xff0c;可以在许多不同…

PHP-FPM 远程代码执行漏洞(CVE-2019-11043)复现

启动容器 docker-compose up -d 查看端口 docker ps 端口为:8080,访问网站&#xff0c;搭建成功 安装漏洞利用工具 攻击 go run . "http://172.16.1.14:8080//index.php" 显示漏洞利用成功&#xff0c;浏览器进行访问&#xff0c;成功复现

微信小程序开发项目详细讲解

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; 微信小程序是一种无需下载安装即可使用的应用程序&#xff0c;基于微信平台开发&#xff0c;能够提供类似原生应用的体验。以下是微信小程序开发的详细讲解&#xff0c;涵盖从项目准备、开发环境搭建到关键…

【无标题】符文价值的退化页

我们利用现有的符文体系建立了一个健全的符文扩展空间&#xff0c;可假若符文让我们感到十分困惑&#xff0c;我们不介意毁灭它们&#xff0c;让一切回到没有字迹的蛮荒纪。 如此&#xff0c;眼睛也失去了作用。我们的成GUO也会给后来者提供又是一DUI 令人眼花缭乱的无用符咒。…

DIC技术助力新能源汽车主机厂力学测试研发与整车性能提升

在新能源汽车研发过程中&#xff0c;非接触式全视场应变DIC测量方案&#xff0c;越来越受到汽车主机厂的信赖与认可。传统接触式传感器&#xff0c;在精度、灵活性和数据处理能力上存在局限。DIC技术可提供精确、高效、全视场、便捷的非接触式测量解决方案。 在汽车研发阶段&a…

OPCUA-PLC

下载opcua服务器(有PLC可以直连),UaAnsiCServer下载路径 双击运行如下,Endpoint显示opcua服务路径 opc.tcp://DESKTOP-9SD7K4B:48020 下载opcua客户端(类似编写代码连接操作),UaExpert下载路径 如果连接失败,有一个授权认证,点击同意就行 java代码实现连接opcUA操作 pom.…