CAS带来的ABA问题以及解决方案

embedded/2024/9/23 10:22:01/

CAS带来的ABA问题

在这里插入图片描述
线程1和线程2同时对变量i = 1 进行操作,线程1对i进行了两次操作,先将i+1 写出,后又进行了i-1并写出,线程2过来读的时候与原来值1仍然是相等的,虽然值仍然相等,但是i的值却发生过改变,期间从1变成2又变成1(ABA问题)。

解决方案

对值的每次操作都进行记录,需要保证是一个原子操作。
在这里插入图片描述
java中使用AtomicMarkableReference或者AtomicStampedReference。
AtomicMarkableReference:使用boolean表示是否修改过。
AtomicStampedReference: 使用int 记录改变的次数(推荐)!

AtomicStampedReference 使用:

java">class Stu {private String name;private Integer age;
getter/setter
}//参数1: 对象 
//参数2:初始版本号AtomicStampedReference<Stu> accountBalance = new AtomicStampedReference<>(stu, 0);源码:
public AtomicStampedReference(V var1, int var2) {this.pair = AtomicStampedReference.Pair.of(var1, var2);
}
static <T> Pair<T> of(T var0, int var1) {return new Pair(var0, var1);  //底层使用Pair对象。
}private Pair(T var1, int var2) {this.reference = var1;  //真实对象this.stamp = var2;   //版本号
}
java">Thread threadA = new Thread(() -> {int[] stampHolder = new int[1];//获取对象Stu stu1 = accountBalance.get(stampHolder);//改变的次数int currentStamp = stampHolder[0];System.out.println("Thread A: 当前年龄 = " + stu1.getAge() + ", 当前版本号= " + currentStamp);stu1.setAge(100000);boolean success = accountBalance.compareAndSet(stu1, stu1, currentStamp, currentStamp + 1);/***源码:* 参数1:  期望值* 参数2:  新值* 参数3: 原有修改次数* 参数4: 新修改次数(一般使用原有修改次数+1)*    public boolean compareAndSet(V var1, V var2, int var3, int var4) {**         //原始对象值  包含对象和修改的次数*         Pair var5 = this.pair;*         return*              var1 == var5.reference  //对象不是同一个(期望值不一样)  就不再进行操作*              && var3 == var5.stamp   // 版本号不一样  就不再进行操作*              && (var2 == var5.reference && var4 == var5.stamp   //操作对象与原来一样并且操作次数也一样 表示中间的值没有被其他线程修改过,无需继续修改*                      ||*                  this.casPair(var5, AtomicStampedReference.Pair.of(var2, var4)));  //进行CAS操作*     }******/if (success) {System.out.println("Thread A: 更新成功,新的年龄 = " + accountBalance.getReference().getAge() + ",新的版本号" + accountBalance.getStamp());} else {System.out.println("Thread A: 更新失败");}});

http://www.ppmy.cn/embedded/105557.html

相关文章

动态爱心绘制:基于 turtle 库的实现

本文将介绍如何使用 Python 中的 turtle 库绘制一组动态移动的爱心形状。通过这段代码&#xff0c;我们可以在屏幕上看到多颗不同颜色、大小的爱心&#xff0c;随着时间随机移动&#xff0c;产生浪漫的动态效果。 1. 项目结构 该程序由一个 Heart 类和一些辅助函数组成。Hear…

投资 - 什么是空中成交

在成交中有个专业名词叫“空中成交”&#xff0c; “空中成交”简单的说就是交易所下属会员【证券公司&#xff0c;具有席位资格投资公司】向交易所的成交捏合处理主机发送买卖交易单时&#xff0c;这些交易单还没有经过交易所对证券公司等行情始终端发送就已经捏合处理成交。这…

Vision Pro开发实践(结合24黑马idea)

这是我参与创作者计划的第1篇文章 开篇 之前写过一篇文章&#xff0c;主要介绍visionPro基本信息、操作和基础适配的文章&#xff1a; 神灯 恰逢2024黑客马拉松举行&#xff0c;我结合本次参赛的一个idea&#xff0c;介绍一下visionOS的开发实践&#xff0c;希望能为大家在进…

深入探索JNI:基础、最佳实践、性能优化与安全策略

文章目录 一、JNI基础入门1.1 概念与工作原理1.2 数据传递机制1.2.1 基本数据类型1.2.2 字符串1.2.3 数组1.2.4 对象 1.3 小结 二、JNI的最佳实践2.1 内存管理2.2 异常处理2.3 线程管理2.4 JNI安全问题 三、JNI性能优化技巧3.1 识别性能瓶颈3.2 本地方法的批处理3.3 减少数据转…

开源平台 Ollama + Langchain:构建智能对话系统的实践指南

文章目录 概要整体架构流程Langchain-Chatchat 模型准备小结 概要 随着自然语言处理&#xff08;NLP&#xff09;技术的发展&#xff0c;开源社区提供了许多强大的工具&#xff0c;帮助开发者构建出更加智能的对话系统。本文将详细介绍如何使用 Ollama 和 Langchain 构建这样一…

opencv图像形态学(边缘检测算法实例)

引言 图像形态学是一种基于数学形态学的图像处理技术&#xff0c;它主要用于分析和修改图像的形状和结构。在OpenCV中&#xff0c;图像形态学操作通过一系列的数学运算来实现&#xff0c;如腐蚀、膨胀、开运算、闭运算等。这些操作在图像处理、计算机视觉和模式识别等领域有着…

github和gitlab的区别是什么

区别&#xff1a;github如果使用私有仓库&#xff0c;是需要付费的&#xff1b;而gitlab可以在上面搭建私人的免费仓库。gitlab让开发团队对他们的代码仓库拥有更多的控制&#xff0c;相对于github&#xff0c;它有不少的特色&#xff1a;允许免费设置仓库权限&#xff1b;可以…

如何在 Java 中实现线程安全的单例模式?

单例模式是一种常用的软件设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点。 在多线程环境下&#xff0c;确保单例模式的线程安全性是非常重要的&#xff0c;因为多个线程可能会同时尝试创建实例&#xff0c;导致实例不唯一的问题。 单例模式…