CAS原理及其API原子类

目录

1.CAS及使用

1.1. CAS概念

1.2.原子类的使用

1.3.CAS使用自旋锁

2.CAS的ABA问题

2.1.问题介绍

2.2.ABA问题解决方式


1.CAS及使用

1.1. CAS概念

(1)CAS,其实是一种操作的简称,全称为:Compare and swap。

(2)通过全称,我们就可以知道,它的作用就是:比较并且交换,这里的操作数不是两个,而是三个。

(3)作用1:类似一个方法,有三个参数,A、V、B

比较A与V比较是否相等;如果相等,将B和A交换;反之,不进行任何操作。

 上述的比较:是将A内存中的值和V寄存器中的值进行比较,如果它们里面的值相等,就会将B寄存器中的值赋值给A内存中。也就是将内存A中的值和寄存器B中的值进行交换,就不会考虑交换后寄存器B中的值。

(4)作用2:CAS可以保证这一系列操作是原子性的(保证线程安全)

上述将了一堆概念,下面介绍使用CAS的使用;因为JVM对CAS进行了封装,所以我们可以直接使用CAS提供的api就可以了。

1.2.原子类的使用

原子类也就是对cas封装后的抽象表示,但是cas不推荐大家使用,性价比低,安全隐患大。

(1)原子类

大约有下面这些原子类,通过下面的类操作一些数,是原子性的。 

这里的类很多,我们这里只介绍一个:AtomicInteger 

(2)AtomicInteger类

这个是我们比较常用的类,是对int的封装,对一个int数据进行++或者--操作,可以保证其是原子性,也就是线程安全。

  • 创造一个AtomicInteger对象
private static AtomicInteger count = new AtomicInteger(0);

这句代码的意思就是:定义一个int遍历count,并且赋值为0,相当于int count = 0;只不过这样创造的变量可以调用这个类里面的方法进行++或者--操作,并且保证原子性。

 

  • 五个方法
方法名作用
getAndIncrement()后置++
incrementAndGet()前置++
getAndDecrement()后置--
decrementAndGet()前置--
getAndAdd()+=操作

演示:

后置++

前置++;

同理:前置--和后置--也是一样的操作

+=操作;

(3)使用AtomicInteger类进行多线程操作

单单使用AtomicInteger操作体现不出来它的特点,我们一样是使用对比手法。

操作:使用两个线程对count各进行50000次++操作

  • 普通int变量
 private static int count = 0;
    public static void main(String[] args) throws InterruptedException {
        System.out.println("++操作前:"+count);
        Thread t1 = new Thread(()->{
            for(int i=0;i<50000;i++) {
                count++;
            }
        });
        Thread t2 = new Thread(()->{
            for(int i=0;i<50000;i++) {
                count++;
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("++操作后:"+count);
    }

明明都++了50000次,但是结果却不是100000,很明显的线程不安全。

  • AtomicInteger变量
 private static AtomicInteger count = new AtomicInteger(0);
    public static void main(String[] args) throws InterruptedException {
        System.out.println("++操作后:"+count);
        Thread t1 = new Thread(()->{
            for(int i=0;i<50000;i++) {
                count.getAndIncrement();
            }
        });
        Thread t2 = new Thread(()->{
            for(int i=0;i<50000;i++) {
                count.getAndIncrement();
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("++操作后:"+count);

    }

结果也是非常的安全呀,这就是原子类的特点

1.3.CAS使用自旋锁

这里我们不作深入的介绍,使用一个伪代码进行介绍即可。

既然是基于自旋锁,那么发挥的作用就类似自旋锁一样。什么是自旋锁:就是当一个锁被占用后,另一个线程再去争夺,机会发生阻塞,此时另一个线程一直在循环等待这把锁释放,就是自旋锁。

  • 伪代码基本介绍

  • CAS部分介绍

这也是就是自旋锁的思想和做法。

2.CAS的ABA问题

cas也是存在问题的,称为ABA问题。

2.1.问题介绍

(1)问题来源

CAS的核心操作是:比较相等,然后进行交换操作。也就是说,只要发现两个对象相等,就会进行交换操作。因此,就会存在一个问题:两个对象相等,但是不代表某个对象没有被修改过,CAS也无法发现问题。也就是其中一个对象的值从A被修改成B,最后又修改回A,然后进行比较操作,也是相等的。

所以ABA问题也就是:CAS无法区分,当前的数据在比较相等前,是否被修改过。

虽然ABA问题产生有危害的Bug几率很小,但是某些情况,就是严重问题。

(2)ABA问题产生的严重BUG例子

举例时间:

场景:PP去ATM前面取钱

假设:PP的余额有1000元,目的要取出500。并且取款的操作是以CAS的方式执行

CAS(A、B、C)

A表示银行卡中应该有的余额数,B表示当前余额,C表示后来的余额

伪代码:

解释一下:比如,我们进入“取款函数”,就会显示余额B=1000元,并且把余额赋值给A(也就是说,当前银行卡里面是有1000元);点击取款500,C=A-500。

此时:如果A==B,说明还未取款成功,就会扣款,也就是A=C,将银行账户里面的钱-500,完成取款500元的操作。此时A!=B,说明已经取款了,就会结束循环,取款操作结束。

上面是我们预期的正常操作,但是如果按照下面的执行,就极有可能发生严重的BUG

极端操作:我们多次点击取款500操作(第一次点击取款未生效,继续第二次),然后这个时候,恰好有另一个人给你转账500元。以上就会产生3个线程

并且按照下面的执行顺序:

这种情况下,也就会产生严重的bug。下面来了解解决方式

2.2.ABA问题解决方式

因为上述的余额是可变的,但是中间是否被修改过,我们也不清楚,所以不能让它来作为CAS的判断依据。

(1)我们引入一个“版本号”作为CAS判断依据,也可以使用其他的变量,规定只能进行单向操作(也就是只能++或者--)

(2)版本号作用:每次操作完成后,版本号都要进行+1操作

(3)示例:

按照这种方式,就可以有效的避免CAS的ABA问题

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HNU-数据库系统-甘晴void学习感悟

前言 过程坎坷&#xff0c;终局满意。 感觉是学懂了知识&#xff0c;并且拿到了分数这样的学科。 【先把这个位置占下来&#xff0c;之后有时间再补充】 教材如下&#xff1a; 总领 有点忘记了&#xff0c;可参考当时记录的笔记&#xff1a; 数据库系统-甘晴void学习笔记-…

【三】Spring Cloud Ribbon 实战

Spring Cloud Ribbon 实战 概述 一直在构思写一个spring cloud系列文章&#xff0c;一方面是对自己实践经验进行一次完整的梳理&#xff0c;另一方面也是希望能够给初学者一些借鉴&#xff0c;让初学者少走些弯路&#xff0c;看到本系列博客就能够很好的把微服务系列组件用好。…

使用QTcpSocket

(1)客户端每隔10ms向服务器发送一次数字字符串&#xff0c;从0开始。 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QTcpSocket> #include <QLabel> #include <QTimer> namespace Ui { class MainWindow; }class Mai…

MAVEN的安装与配置

MAVEN的安装与配置 1 简介 1.1 什么是MAVEN? Maven是一个项目构建及管理工具&#xff0c;开发团队几乎不用花多少时间就能够自动完成工程的基础构建配置&#xff0c; Maven 使用了一个标准的目录结构在不同开发工具中也能实现项目结构的统一。Maven提供了清理&#xff0c;编…

【Vue】组件化编程

定义 实现应用中局部功能代码和资源的集合 为什么要用组件化编程? 传统方式编写:依赖关系混乱,不好维护,且代码复用率不高 模块化编写:只关注解决js,复用js,简化js的编写与效率 组件方式编写:好维护、复用率更高、提高运行效率 在组件出现之前,我们开发基本都是用htm…

【综述】DSP处理器芯片

文章目录 TI DSP C2000系列 TMS320F28003X 典型应用 开发工具链 参考资料 TI DSP TI C2000系列 控制领域 TI C5000系列 通信领域 TI C6000系列 图像领域 C2000系列 第三代集成了C28浮点DSP内核&#xff0c;采用了65nm工艺&#xff08;上一代180nm&#xff09; 第四代正在…

PyCharm 无法运行的解决方案

问题&#xff1a; PyCharm 无法运行&#xff0c;该怎么办&#xff1f; 解决方案&#xff1a; 1. 检查 Python 解释器 确保已为 PyCharm 配置正确的 Python 解释器。打开 PyCharm&#xff0c;转到“文件”>“设置”>“项目”>“Python 解释器”。选择所需的 Python …

怎么在海外平台买东西?Nike海淘攻略

不管在那个海外平台买东西首先要进入官网&#xff0c;最好注册一个gmail账号&#xff0c;这样使用范围比较宽广&#xff0c;在对应平台进行注册账号&#xff0c;比如亚马逊、ebay、Etsy等等 一、Nike海淘攻略 1、然后如果已经会员的话直接输入账号密码登录&#xff0c;如果不…

AI大模型探索之路-训练篇3:大语言模型全景解读

文章目录 前言一、语言模型发展历程1. 第一阶段&#xff1a;统计语言模型&#xff08;Statistical Language Model, SLM&#xff09;2. 第二阶段&#xff1a;神经语言模型&#xff08;Neural Language Model, NLM&#xff09;3. 第三阶段&#xff1a;预训练语言模型&#xff08…

顺通拖鞋ERP企业销售管理系统:驱动销售业绩飙升的利器

顺通企业销售管理系统通过集成客户信息、销售流程、数据分析等功能&#xff0c;帮助企业全面提升销售效率和业绩&#xff0c;成为驱动销售业绩飙升的利器。此外&#xff0c;系统还支持销售流程的可视化展示&#xff0c;使销售人员能够清晰地了解销售进展&#xff0c;及时调整销…

短视频账号矩阵系统===4年技术源头打磨

短视频矩阵系统技术源头打磨需要从多个方面入手&#xff0c;以下是一些建议&#xff1a; 1. 基础技术研发&#xff1a;不断投入资金和人力进行基础技术研发&#xff0c;包括但不限于视频处理、人工智能、大数据等技术&#xff0c;以提高短视频矩阵系统的性能和稳定性。 2. 优化…

JAVA面试八股文之JVM

JVM JVM由那些部分组成&#xff0c;运行流程是什么&#xff1f;你能详细说一下 JVM 运行时数据区吗&#xff1f;详细介绍一下程序计数器的作用&#xff1f;你能给我详细的介绍Java堆吗?什么是虚拟机栈&#xff1f;栈内存溢出情况&#xff1f;堆栈的区别是什么吗&#xff1f;解…

深入理解分布式事务② ---->分布式事务基础(MySQL 的 4 种事务隔离级别【读未提交、读已提交、可重复读、串行化】的最佳实践演示)详解

目录 深入理解分布式事务② ----&#xff1e;分布式事务基础&#xff08;MySQL 的 4 种事务隔离级别【读未提交、读已提交、可重复读、串行化】的最佳实践演示&#xff09;详解1、MySQL 事务基础1-1&#xff1a;MySQL 中 4 种事务隔离级别的区别1-2&#xff1a;MySQL 中 4 种事…

Qt使用OPCUA

假如想在Qt下使用OPCUA通讯&#xff0c;貌似大家都是倾向于使用【qtopcua】这个库。但是在Qt6之前&#xff0c;假如想使用这个库&#xff0c;还得自己编译&#xff0c;比较繁琐。假如想开箱即用&#xff0c;而且没有使用太复杂的功能的话&#xff0c;其实可以直接使用open62541…

2024年最新一线互联网企业高级软件测试工程师面试题大全

1、功能测试 功能测试是游戏测试中跟“玩游戏”最相关的一个环节。 当然这里的“玩”不是要真的让你感受快乐&#xff0c;而是要通过“玩”游戏&#xff0c;发现存在的问题或不合理的地方。因此&#xff0c;这个“玩”的过程基本不会感受到游戏的乐趣。事实上&#xff0c;每一次…

决策树学习笔记

一、衡量标准——熵 随机变量不确定性的度量 信息增益&#xff1a;表示特征X使得类Y的不确定性减少的程度。 二、数据集 14天的打球情况 特征&#xff1a;4种环境变化&#xff08;天气、温度等等&#xff09; 在上述数据种&#xff0c;14天中打球的天数为9天&#xff1b;不…

LVGL移植

Lvgl介绍 LVGL是一个开源的图形库&#xff0c;专为嵌入式系统设计。它提供了丰富的图形元素和功能&#xff0c;可以帮助开发者快速构建现代化的用户界面。LVGL具有跨平台的特性&#xff0c;支持多种操作系统和硬件平台&#xff0c;包括ARM Cortex-M&#xff0c;ESP32&#xff…

基于springboot+vue+Mysql的漫画网站

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

等保测评与信息安全管理体系认证的区别

区别一、标准以及性质 等保测评以《中华人民共和国计算机信息系统安全保护条例》为基础&#xff0c;结合一系列的政策和标准&#xff0c;对信息安全水平进行评估。而安全管理系统的认证&#xff0c;是资讯安全管理系统的一种规范&#xff0c;本身并不具备强制性质。企业可根据…

这么全的权限系统设计方案,不值得收藏吗?

1 为什么需要权限管理 日常工作中权限的问题时时刻刻伴随着我们&#xff0c;程序员新入职一家公司需要找人开通各种权限&#xff0c;比如网络连接的权限、编码下载提交的权限、监控平台登录的权限、运营平台查数据的权限等等。 在很多时候我们会觉得这么多繁杂的申请给工作带…