首页 > 编程语言 >【JavaEE】——CAS指令和ABA问题

【JavaEE】——CAS指令和ABA问题

时间:2024-09-29 17:49:59浏览次数:7  
标签:ABA CAS 代码 JavaEE 穿插 原子 指令 线程

8e19eee2be5648b78d93fbff2488137b.png

阿华代码,不是逆风,就是我疯

你们的点赞收藏是我前进最大的动力!!

希望本文内容能够帮助到你!!

目录

一:CAS指令

1:概念

2:伪代码例子说明

3:优点

二:原子类

1:引入

2:代码示例

3:与volatile的区别

4:标准库源码

三:CAS是如何避免线程安全问题

四:CAS中ABA问题

1:引入

2:极端情况

3:解决方案


一:CAS指令

1:概念

CAS是CPU中的一条特殊的指令,它的功能就是完成“比较和交换”

2:伪代码例子说明

伪代码:只能表示一种逻辑,并不能实现编译执行

注:CAS指令一般只关注内存当中的值,就存起当中的值是多少不打紧,用完就不要了

3:优点

CAS指令不涉及锁,也能保证线程的安全

二:原子类

1:引入

在Java中:

先是操作系统对指令封装成api

然后JVM在对api进行封装,把CAS的api放到了unsafe这个包里(注:这个包里指令会涉及一些系统底层的内容,使用的话是风险操作)

Java标准库中,对CAS再进一步封装,提供了一些工具类,其中最主要的一个工具叫“原子类”

java.util.concurrent.atomic

2:代码示例

我们还是沿用【JavaEE】——线程的安全问题和解决方式_java线程安全 线程不安全-CSDN博客

这篇文章中,用两个线程去自增到10000计数器这个例子

前面我们是通过synchronized加锁方式解决,这里我们使用原子类进行代码编译

package thread;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Hua YY
 * Date: 2024-09-29
 * Time: 14:15
 */
public class ThreadDemon36 {

   // private static int result = 0;
    //括号里的参数就是result的初始值
    private static AtomicInteger result = new AtomicInteger(0);
    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(() -> {
           for(int i = 1 ; i <= 5000 ; i++){
               result.getAndIncrement();//自增相当于result++
               //result++;

           }
        });
        Thread t2 = new Thread(() -> {
            for(int i = 1 ; i <= 5000 ; i++){
                result.getAndIncrement();//自增
                //result++;
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(result.get());//获取到result中持有的值
    }
}

 

这里的++操作,不在是(load,add,save)三条指令了,而是打包成了CAS指令,成为一个天然的原子性指令,这样就避免了,多线程中两者的指令相互穿插执行,也就避免了线程安全问题

(1)方法总结

①.getAndIncrement()——相当于count++

②.incrementAndGet()——相当于++count

3:与volatile的区别

volatile是禁止指令重排序(因为操作非原子性嘛),

4:标准库源码

三:CAS是如何避免线程安全问题

核心点:就是通过CAS和while循环的搭配,来确保内存中的值和寄存器当中的值是一样的, 

这里的代价就是“自旋”——while循环嘛,但是一般循环不了几次就OK了,这点资源损耗可以忽略

不计,CAS还是很香的~~~

四:CAS中ABA问题

1:引入

上述图文看明白之后,我们可以总结出一点,CAS判断内存和寄存器中的值是否相等,本质上就是在判断——是否有其他线程穿插指令

想象一下,在CAS之前,如果有一个线程穿插进去把数值修改了,紧接着第二个线程也穿插进去把错误的数值又修改回来了,那么CAS是感知不到有线程穿插进来的(如穿~~)

一般来说这也不会引起什么bug之类的

2:极端情况

存钱

3:解决方案

(1)约定数据变化本身就是单向的,只能增加或者只能减少

(2)对于本身必须就是双向变化的数据,引入一个版本号——这个版本号就是只能增加不能减少

标签:ABA,CAS,代码,JavaEE,穿插,原子,指令,线程
From: https://blog.csdn.net/2301_80133875/article/details/142633713

相关文章

  • CAS原子类:AtomicLongArray源码解析
    AtomicLongArray内部维护了一个int类型的数组,需要先复习下数组对象的在内存中的结构,这对接下来对数组类型原子类的理解至关重要。一、数组对象的内存结构我们运行以下代码并将数组对象的内存结构通过JOL工具打印出来,关于这部分知识,参考之前的文章:深入理解Java对象结构publiccl......
  • C++ const_cast 和重载
    在4.11.3节(第145页)中我们说过,const_cast在重载函数的情景中最有用。举个例子,回忆6.3.2节(第201页)的shorterstring函数://比较两个string对象的长度,返回较短的那个引用conststring&shorterString(conststring&sl,conststring&s2){returnsl.size()<=s2.size()?......
  • 解决Kuboard etcd 空间超过2G报:etcdserver: mvcc: database space exceeded。无法访问
    解决Kuboardetcd空间超过2G后无法访问问题Kuboard突然无法访问,使用kubernetes运行的kuboard参考:https://github.com/eip-work/kuboard-press/issues/526https://blog.csdn.net/wdy_2099/article/details/133203698排查问题查看日志信息通过查看pod日志看到错误信息......
  • GaussDB SQL基本语法示例-CASE表达式
    一、前言SQL是用于访问和处理数据库的标准计算机语言。GaussDB支持SQL标准(默认支持SQL2、SQL3和SQL4的主要特性)。本系列将以《云数据库GaussDB—SQL参考》在线文档为主线进行介绍。二、CASEExpression(CASE表达式)介绍在GaussDBSQL中,CASE表达式(CASEExpression)是一个非常强大......
  • JavaEE初阶——认识操作系统
    目录一、操作系统1、概念2、操作系统的定位二、什么是进程1、什么是进程/任务(Process/Task)2、进程的描述与组织3、PCB中描述进程的特征4、进程调度的相关属性1、进程的状态2、优先级3、上下文4、记账信息三、内存管理1、虚拟地址空间2、进程的内存分配一、......
  • Mysql8.0启动时出现ERROR: Different lower_case_table_names settings for server ('
    分析:出现这个原因数据库启动后,调整lower_case_table_names参数导致的这个问题。mysql8.0之后,lower_case_table_names配置必须在安装好MySQL后,初始化mysql配置时才有效。一旦mysql启动后,再设置是无效的,而且启动报错。lower_case_table_names=1表示mysql是不区分大小写的......
  • 学习011-03-01 Business Classes vs Database Tables(业务类与数据库表)
    BusinessClassesvsDatabaseTables(业务类与数据库表)TheXAFisbasedonanobject-baseddatahandlingapproach.Inthistopic,wediscussthereasonswhythisapproach,asopposedtotherelationalmodelofdatahandling,waschosen.Themethodsthatal......
  • 电商API数据接口1688alibaba接口item_search_shop-获得店铺的所有商品接入演示
    一、接口功能item_search_shop接口是1688阿里巴巴提供的获取店铺所有商品的API接口,用户可以通过输入店铺ID,获取该店铺的所有商品信息。二、接口调用请求参数:seller_nick=b2b-2200733087881719de&start_price=0&end_price=0&q=&page=1&cid=参数说明:seller_nick:sid或者加密后的_sopi......
  • Database Server Error怎么办
    遇到“DatabaseServerError”通常意味着在尝试访问或操作数据库时遇到了问题。这类错误可能由多种原因引起,下面是一些常见的解决步骤:检查连接信息:确认数据库的用户名、密码、主机地址和端口是否正确。检查网络连接是否正常。查看错误日志:查看应用程序的日志文件,通常......
  • 教你玩转MySQL8物理备份利器Xtrabackup
    教你玩转MySQL8物理备份利器Xtrabackup原创 我科绝伦 小周的数据库进阶之路  2024年09月22日00:00 重庆热衷于分享各种干货知识,大家有想看或者想学的可以评论区留言,秉承着“开源知识来源于互联网,回归于互联网”的理念,分享一些日常工作中能用到或者频率比较的内容,......