广告
返回顶部
首页 > 资讯 > 后端开发 > Python >分析ABA问题的本质及其解决办法
  • 728
分享到

分析ABA问题的本质及其解决办法

2024-04-02 19:04:59 728人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录简介第一类问题第二类问题第一类问题的解决第二类问题的解决总结简介 CAS的原理其实很简单,为了保证在多线程环境下我们的更新是符合预期的,或者说一个线程在更新某个对象的时候,没有其

简介

CAS的原理其实很简单,为了保证在多线程环境下我们的更新是符合预期的,或者说一个线程在更新某个对象的时候,没有其他的线程对该对象进行修改。在线程更新某个对象(或值)之前,先保存更新前的值,然后在实际更新的时候传入之前保存的值,进行比较,如果一致的话就进行更新,否则失败。

注意,CAS在java中是用native方法来实现的,利用了系统本身提供的原子性操作。

那么CAS在使用中会有什么问题呢?一般来说CAS如果设计的不够完美的话,可能会产生ABA问题,而ABA问题又可以分为两类,我们先看来看一类问题。

第一类问题

我们考虑下面一种ABA的情况:

1.在多线程的环境中,线程a从共享的地址X中读取到了对象A。

2.在线程a准备对地址X进行更新之前,线程b将地址X中的值修改为了B。

3.接着线程b将地址X中的值又修改回了A。

4.最新线程a对地址X执行CAS,发现X中存储的还是对象A,对象匹配,CAS成功。

上面的例子中CAS成功了,但是实际上这个CAS并不是原子操作,如果我们想要依赖CAS来实现原子操作的话可能就会出现隐藏的bug。

第一类问题的关键就在2和3两步。这两步我们可以看到线程b直接替换了内存地址X中的内容。

在拥有自动GC环境的编程语言,比如说java中,2,3的情况是不可能出现的,因为在java中,只要两个对象的地址一致,就表示这两个对象是相等的。

2,3两步可能出现的情况就在像c++这种,不存在自动GC环境的编程语言中。因为可以自己控制对象的生命周期,如果我们从一个list中删除掉了一个对象,然后又重新分配了一个对象,并将其add back到list中去,那么根据 MRU memory allocation算法,这个新的对象很有可能和之前删除对象的内存地址是一样的。这样就会导致ABA的问题。

第二类问题

如果我们在拥有自动GC的编程语言中,那么是否仍然存在CAS问题呢?

考虑下面的情况,有一个链表里面的数据是A->B->C,我们希望执行一个CAS操作,将A替换成D,生成链表D->B->C。考虑下面的步骤:

1.线程a读取链表头部节点A。

2.线程b将链表中的B节点删掉,链表变成了A->C

3.线程a执行CAS操作,将A替换从D。

最后我们的到的链表是D->C,而不是D->B->C。

问题出在哪呢?CAS比较的节点A和最新的头部节点是不是同一个节点,它并没有关心节点A在步骤1和3之间是否内容发生变化。

我们举个例子:


public void useABAReference(){
    CustUser a= new CustUser();
    CustUser b= new CustUser();
    CustUser c= new CustUser();
    AtomicReference<CustUser> atomicReference= new AtomicReference<>(a);
    log.info("{}",atomicReference.compareAndSet(a,b));
    log.info("{}",atomicReference.compareAndSet(b,a));
    a.setName("change for new name");
    log.info("{}",atomicReference.compareAndSet(a,c));
}

上面的例子中,我们使用了AtomicReference的CAS方法来判断对象是否发生变化。在CAS b和a之后,我们将a的name进行了修改,我们看下最后的输出结果:

[main] INFO com.flydean.aba.ABAUsage - true

[main] INFO com.flydean.aba.ABAUsage - true

[main] INFO com.flydean.aba.ABAUsage - true

三个CAS的结果都是true。说明CAS确实比较的两者是否为统一对象,对其中内容的变化并不关心。

第二类问题可能会导致某些集合类的操作并不是原子性的,因为你并不能保证在CAS的过程中,有没有其他的节点发送变化。

第一类问题的解决

第一类问题在存在自动GC的编程语言中是不存在的,我们主要看下怎么在C++之类的语言中解决这个问题。

根据官方的说法,第一类问题大概有四种解法:

1.使用中间节点 - 使用一些不代表任何数据的中间节点来表示某些节点是标记被删除的。

2.使用自动GC。

3.使用hazard pointers - hazard pointers 保存了当前线程正在访问的节点的地址,在这些hazard pointers中的节点不能够被修改和删除。

4.使用read-copy update (RCU) - 在每次更新的之前,都做一份拷贝,每次更新的是拷贝出来的新结构。

第二类问题的解决

第二类问题其实算是整体集合对象的CAS问题了。一个简单的解决办法就是每次做CAS更新的时候再添加一个版本号。如果版本号不是预期的版本,就说明有其他的线程更新了集合中的某些节点,这次CAS是失败的。

我们举个AtomicStampedReference的例子:


public void useABAStampReference(){
    Object a= new Object();
    Object b= new Object();
    Object c= new Object();
    AtomicStampedReference<Object> atomicStampedReference= new AtomicStampedReference(a,0);
    log.info("{}",atomicStampedReference.compareAndSet(a,b,0,1));
    log.info("{}",atomicStampedReference.compareAndSet(b,a,1,2));
    log.info("{}",atomicStampedReference.compareAndSet(a,c,0,1));
}

AtomicStampedReference的compareAndSet方法,多出了两个参数,分别是expectedStamp和newStamp,两个参数都是int型的,需要我们手动传入。

总结

ABA问题其实是由两类问题组成的,需要我们分开来对待和解决。

以上就是分析ABA问题的本质及其解决办法的详细内容,更多关于ABA问题的本质及其解决办法的资料请关注编程网其它相关文章!

--结束END--

本文标题: 分析ABA问题的本质及其解决办法

本文链接: https://www.lsjlt.com/news/127409.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 分析ABA问题的本质及其解决办法
    目录简介第一类问题第二类问题第一类问题的解决第二类问题的解决总结简介 CAS的原理其实很简单,为了保证在多线程环境下我们的更新是符合预期的,或者说一个线程在更新某个对象的时候,没有其...
    99+
    2022-11-12
  • Android 关于“NetworkOnMainThreadException”问题的原因分析及解决办法
    网络收集的原因如下,以及解决办法: 我补充总结一下: 解决办法一: 在操作网络类(socket连接)的activity的protected void onCreate(Bu...
    99+
    2022-06-06
    Android
  • vue-cli空格报错问题的分析及解决办法
    作为前端开发者,我们经常会使用到 Vue.js 框架,而在 Vue.js 开始学习阶段,我们更多时候会借助 vue-cli 工具来快速构建和管理项目,然而 vue-cli 工具在使用过程中,我们也可能会遇到一些问题。本篇文章就来跟大家分享一...
    99+
    2023-05-14
  • MySQL8.0+版本1045错误的问题及解决办法
    目录一、管理员权限打开CMD二、CD到自己的mysql安装目录三、停止MySQL服务四、键入命令行五、重新打开CMD窗口六、登录MySQL数据库七、密码改为空密码八、刷新数据九、退出数据库十、启动MySQL服务十一、命令...
    99+
    2022-08-23
  • MySQL死锁问题的分析及解决方法
    这篇文章主要讲解了“MySQL死锁问题的分析及解决方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL死锁问题的分析及解决方法”吧!MySQL死锁问...
    99+
    2022-10-18
  • 分析MySQL并发下的问题及解决方法
    1、背景 对于数据库系统来说在多用户并发条件下提高并发性的同时又要保证数据的一致性一直是数据库系统追求的目标,既要满足大量并发访问的需求又必须保证在此条件下数据的安全,为了满足这一目标大多数数据库通过锁和事...
    99+
    2022-10-18
  • Oracle nvarchar2错误的问题分析及解决方法
    本篇内容主要讲解“Oracle nvarchar2错误的问题分析及解决方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Oracle nvarchar2错误的问...
    99+
    2022-10-18
  • java 中 poi解析Excel文件版本问题解决办法
    poi解析Excel文件版本问题解决办法poi解析Excel文件时有两种格式: HSSFWorkbook格式用来解析Excel2003(xls)的文件 XSSFWorkbook格式用来解析Excel2007(xlsx)的文件 如果用HSSF...
    99+
    2023-05-31
    poi excel ava
  • MySQL 实例无法启动的问题分析及解决
    前言 前几天,有位朋友微信联系我,告知一个生产数据库,在机器宕机恢复后,实例启动失败,而且该实例没有做任何的高可用、容灾、备份等,对业务影响非常大,希望能够协助排查一下,我也在第一时间就加入到排查中。 场景分析 ...
    99+
    2022-05-26
    MySQL 实例启动 MySQL 多实例
  • Pandas出现KeyError的问题解决及分析
    目录写在前面报错详细信息问题解决举一反三写在前面 今天在用爬虫及Pandas更新股票日线数据的时候发现KeyError报错,后面跟了一个DataFrame列索引,一开始以为是索引修改...
    99+
    2023-01-17
    Pandas KeyError
  • SpringIOC能降低耦合的问题分析及解决方法
    目录一、传统方式创建对象二、接口编程三、工厂方法四、反射五、Spring IOC总结有同学在学习 Spring 框架中可能会问这样的问题,为什么通过依赖注入就可以降低代码间的耦合呢?...
    99+
    2022-11-13
  • 解决mysql5.7及以下版本无法解析json字符串的问题
    #把key->value(json字符串)拼成sql语句DELIMITER //DROP FUNCTION kvJsonData//CREATE FUNCTION kvJsonData(tableNa...
    99+
    2022-10-18
  • "Method Not Allowed"405问题分析以及解决方法
    目录背景:现象:排查解决过程:总结:首先,明确一点405问题就是浏览器端(或客户端)请求方法和服务端处理该路径的请求的处理方法不一致造成的。 背景: SpringBoot2.70整合...
    99+
    2022-11-13
    405 method not allowed是什么原因 405 not allowed怎么解决 405not allowed
  • Win8.1预览版常见问题以及解决办法大全(分享)
    微软Win8.1预览版常见问题及解答大全: 一、 什么是Windows 8.1 Preview? Windows 8.1 Preview和Windows RT 8.1 Preview是Windows 8.1...
    99+
    2022-06-04
    常见问题 解决办法 预览版
  • Win7系统安装遇到的问题及解决办法
        问题1:屏幕出现Please wait...等待许久不见动静   解决方法:这是Win7安装开始时安装程序加载时的提示语。如果卡在这个地方无法进行下去,请检查电脑硬件是否正常工作。但是如果电脑本身配置较...
    99+
    2023-06-03
    Win7 问题 系统 解决办法
  • java应用cpu占用过高问题分析及解决方法
    使用jstack分析java程序cpu占用率过高的问题1,使用jps查找出java进程的pid,如37072,使用top -p 14292 -H观察该进程中所有线程的CPU占用。[root@cp01-game-dudai-0100.cp01...
    99+
    2023-05-31
    java cpu ava
  • 分析Git认证失败的原因及解决办法
    前言Git是目前最主流的代码管理和版本控制工具之一,在企业和开源社区广泛使用。在使用 Git 进行代码管理时,可能会遇到 Git 认证失败的问题。本文将分析Git认证失败的原因及可能的解决方法。一、Git认证失败的原因1.凭证缓存失效在使用...
    99+
    2023-10-22
  • win7系统无法加右键启动问题分析及解决方法
    问题描述: 一般在gvim安装完之后,选中文件点击右键会有一个使用gvim打开的选项,但这个在vista上: 通过修改regedit来添加一个gvim项。 复制代码代码如下: HKEY_LOCAL_MACHINE\SOF...
    99+
    2023-05-29
    win7 右键启动 问题 启动 分析 系统
  • 关于css样式被覆盖的问题,及其解决方法
    当你给一个div添加一个class类名的时候,样式未显示的时候 例如: 首先第一步,打开f12标签上查看是否这个类名 此时会出现两种情况 第一种是类名未加上,此时应该查看class是否加错了标签 第二种情况就是,class加上去了,但是样...
    99+
    2023-08-31
    css 前端 html css3 javascript
  • 总结分析Git pull 常见的错误及其解决方法
    在使用 Git 进行项目协作时,我们经常会使用 git pull 命令来同步远程仓库中的代码到本地。尽管这个命令非常简单易用,但有时候可能会遇到各种各样的错误,甚至导致项目无法正常运行。本文将分析 Git pull 常见的错误及其解决方法。...
    99+
    2023-10-22
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作