CAS -- ABA问题的解决方案
我们现在来说什么是ABA问题。假设内存中有一个值为A的变量,存储在地址V中。
此时有三个线程想使用CAS的方式更新这个变量的值,每个线程的执行时间有略微偏差。线程1和线程2已经获取当前值,线程3还未获取当前值。
接下来,线程1先一步执行成功,把当前值成功从A更新为B;同时线程2因为某种原因???被阻塞住,没有做更新操作;线程3在线程1更新之后,获取了当前值B。
为什么线程3又反过来操作???是自旋吗???
在之后,线程2仍然处于阻塞状态,线程3继续执行,成功把当前值从B更新成了A。
最后,线程2终于恢复了运行状态,由于阻塞之前已经获得了“当前值A”,并且经过compare检测,内存地址V中的实际值也是A,所以成功把变量值A更新成了B。
个人见解: 不是说一定出现ABA情况,是说有出现这种情况的可能性。也就是举一个特例来说明问题的可能性???
看起来这个例子没啥问题,但如果结合实际,就可以发现它的问题所在。
我们假设一个提款机的例子。假设有一个遵循CAS原理的提款机,小灰有100元存款,要用这个提款机来提款50元 。
由于提款机硬件出了点问题,小灰的提款操作被同时提交了两次,开启了两个线程,两个线程都是获取当前值100元,要更新成50元。
理想情况下,应该一个线程更新成功,一个线程更新失败,小灰的存款值被扣一次。
有个问题: 点两次正常情况下不是两次都成功吗?为什么一次成功一次失败???
线程1首先执行成功,把余额从100改成50.线程2因为某种原因 什么原因???阻塞。这时,小灰的妈妈刚好给小灰汇款50元。
线程2仍然是阻塞状态,线程3执行成功,把余额从50改成了100。
线程2恢复运行,由于阻塞之前获得了“当前值”100,并且经过compare检测,此时存款实际值也是100,所以会成功把变量值100更新成50。
原本线程2应当提交失败,小灰的正确余额应该保持100元,结果由于ABA问题提交成功了。
怎么解决呢?加个版本号就可以了。
真正要做到严谨的CAS机制,我们在compare阶段不仅要比较期望值A和地址V中的实际值,还要比较变量的版本号是否一致。
我们仍然以刚才的例子来说明,假设地址V中存储着变量值A,当前版本号是01。线程1获取了当前值A和版本号01,想要更新为B,但是被阻塞了。
这时候,内存地址V中变量发生了多次改变,版本号提升为03,但是变量值仍然是A。
随后线程1恢复运行,进行compare操作。经过比较,线程1所获得的值和地址的实际值都是A,但是版本号不相等,所以这一次更新失败。
在Java中,AtomicStampedReference类???就实现了用版本号作比较额CAS机制。
1. java语言CAS底层如何实现?
利用unsafe提供的原子性操作方法(我也不太清楚???)。
2.什么事ABA问题?怎么解决?
当一个值从A变成B,又更新回A,普通CAS机制会误判通过检测。
利用版本号比较可以有效解决ABA问题。
参考文档:https://blog.csdn.net/qq_32998153/article/details/79529704
CAS -- ABA问题的解决方案的更多相关文章
- CAS导致的ABA问题以及解决方案
CAS算法实现一个重要前提需要取出内存中某时刻的数据,而在下时刻比较并替换,那么在这个时间差类会导致数据的变化. 上篇文章讲到CAS会出现一个ABA问题.那什么是ABA问题呢? 官方一点的解释就是:当 ...
- CAS / ABA
CAS / ABA 标签(空格分隔): 操作系统 1. CAS 解决 Volatile 不保证原子性的问题 /** * Atomically increments by one the current ...
- JDK对CAS ABA问题解决-AtomicMarkableReference和AtomicStampedReference
我们知道AtomicInteger和AtomicLong的原子操作,但是在这两个类在CAS操作的时候会遇到ABA问题,可能大家会疑问什么是ABA问题呢,请待我细细道来: ABA问题:简单讲就是多线程环 ...
- Java并发编程原理与实战四十三:CAS ---- ABA问题
CAS(Compare And Swap)导致的ABA问题 问题描述 多线程情况下,每个线程使用CAS操作欲将数据A修改成B,当然我们只希望只有一个线程能够正确的修改数据,并且只修改一次.当并发的时候 ...
- Java CAS ABA问题发生的场景分析
提到了CAS操作存在问题,就是在CAS之前A变成B又变回A,CAS还是能够设置成功的,什么场景下会出现这个问题呢?查了一些资料,发现在下面的两种情况下会出现ABA问题. 1.A最开始的内存地址是X,然 ...
- CAS ABA问题
java.util.concurrent包的最底层基础CAS技术,原理很简单. CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B.当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什 ...
- DLC双端锁,CAS,ABA问题
一.什么是DLC双端锁?有什么用处? 为了解决在多线程模式下,高并发的环境中,唯一确保单例模式只能生成一个实例 多线程环境中,单例模式会因为指令重排和线程竞争的原因会出现多个对象 public cla ...
- 一篇文章快速搞懂 Atomic(原子整数/CAS/ABA/原子引用/原子数组/LongAdder)
前言 相信大部分开发人员,或多或少都看过或写过并发编程的代码.并发关键字除了Synchronized,还有另一大分支Atomic.如果大家没听过没用过先看基础篇,如果听过用过,请滑至底部看进阶篇,深入 ...
- CAS与ABA问题产生和解决
乐观锁和悲观锁 Synchronized属于悲观锁,悲观地认为程序中的并发情况严重,所以严防死守.CAS属于乐观锁,乐观地认为程序中的并发情况不那么严重,所以让线程不断去尝试更新. 性能对比: Syn ...
随机推荐
- Codeforces New Year and Arbitrary Arrangement
New Year and Arbitrary Arrangement time limit per test2 seconds You are given three integers k, pa a ...
- ubuntu安装goland
安装goland 首先下载goland https://www.jetbrains.com/zh/go/specials/go/go.html?utm_source=baidu&utm_med ...
- shell date 格式化
https://www.tutorialkart.com/bash-shell-scripting/bash-date-format-options-examples/ DATE=`date '+%d ...
- 使用ReadStream方法读取文件事件传递过程
const fs = require('fs'); let file = fs.createReadStream("filename.js"); file.on("ope ...
- 路由网关--spring cloud zuul
路由网关--spring boot Zuul 1.为什么需要Zuul? Zuul Ribbon 以及 Eureka 相结合,可以实现智能路由和负载均衡的功能, Zuul 能够将请求流量按某种策略分发到 ...
- Service5
DHCP概述及原理• Dynamic Host Configuration Protocol – 动态主机配置协议,由 IETF(Internet 网络工程师任务小组)组织制定,用来简化主机地址分配 ...
- delphi 文件分割与合并
流的使用分割与合并文件的函数 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, ...
- 二:unittest框架配合selenium之xpath定位
刚开始学习selenium自动化测试时,犯了一个不该犯的错误,偷懒,使用火狐浏览器中的扩展FIREBUG,FIREPATH来辅助定位. 虽然用的定位方法大多数是使用XPATH方法,但是是工具定位出来的 ...
- share memory
header for public argument:shmdata.h #define TEXT_SZ 2048 struct shared_use_st { int written; char t ...
- 您应升级到 MySQL 5.5.0 或更高版本。 phpmyadmin
最近又折腾LAMP了.从官方下载的phpmyadmin在部署的时候发现 “您应升级到 MySQL 5.5.0 或更高版本”.原因是我安装的mysql数据库版本过低. 解决思路: 1.升级mysql版本 ...