当前位置: 首页 > news >正文

AtomicStampedReference解决方案

1、通过引入版本戳(stamp)机制解决ABA问题:

  • 每次修改时递增版本号
  • 执行CAS时同时检查值和版本号
  • 即使值相同但版本不同,操作也会失败
    在这里插入图片描述

2、具体代码实现

import java.util.concurrent.atomic.AtomicStampedReference;public class AtomicStampedReferenceDemo {// 账户余额初始值为100,版本号初始为0private static final AtomicStampedReference<Integer> accountBalance =new AtomicStampedReference<>(100, 0);public static void main(String[] args) throws InterruptedException {System.out.println("============== AtomicStampedReference解决ABA问题 ==============");System.out.println("初始账户余额: " + accountBalance.getReference() +"元, 版本号: " + accountBalance.getStamp());System.out.println();// 创建ABA操作线程Thread abaThread = new Thread(() -> {int[] stampHolder = new int[1];int currentValue;// 第一次修改:10050System.out.println(stampHolder[0]);currentValue = accountBalance.get(stampHolder);int currentStamp = stampHolder[0];System.out.println("[ABA线程] 读取余额: " + currentValue + "元, 版本: " + currentStamp);boolean success = accountBalance.compareAndSet(currentValue,50,currentStamp,currentStamp + 1);System.out.println("[ABA线程] 修改余额为50: " + (success ? "成功" : "失败") +", 新版本: " + accountBalance.getStamp());System.out.println("当前余额: " + accountBalance.getReference() + "元");System.out.println();// 第二次修改:50 → 100currentValue = accountBalance.get(stampHolder);currentStamp = stampHolder[0];System.out.println("[ABA线程] 读取余额: " + currentValue + "元, 版本: " + currentStamp);success = accountBalance.compareAndSet(currentValue,100,currentStamp,currentStamp + 1);System.out.println("[ABA线程] 恢复余额为100元: " + (success ? "成功" : "失败") +", 新版本: " + accountBalance.getStamp());System.out.println("当前余额: " + accountBalance.getReference() + "元");System.out.println();});// 创建转账线程Thread transferThread = new Thread(() -> {int[] stampHolder = new int[1];int currentValue = accountBalance.get(stampHolder);int currentStamp = stampHolder[0];System.out.println("[转账线程] 读取余额: " + currentValue + "元, 版本: " + currentStamp);System.out.println("[转账线程] 开始处理转账...");try {// 模拟处理耗时Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("[转账线程] 转账处理完成,尝试更新账户");// 尝试更新余额(增加50元)boolean success = accountBalance.compareAndSet(currentValue,currentValue + 50,currentStamp,currentStamp + 1);System.out.println("\n===== 转账操作结果 =====");System.out.println("操作结果: " + (success ? "成功" : "失败"));System.out.println("预期版本: " + currentStamp + ", 实际版本: " + accountBalance.getStamp());System.out.println("预期余额: " + currentValue + "元, 当前余额: " + accountBalance.getReference() + "元");System.out.println("=====================\n");});// 启动线程transferThread.start();Thread.sleep(500); // 确保转账线程先读取初始值abaThread.start();// 等待线程完成abaThread.join();transferThread.join();System.out.println("\n最终账户余额: " + accountBalance.getReference() + "元, 版本号: " + accountBalance.getStamp());System.out.println("============== 演示结束 ==============");}
}
============== AtomicStampedReference解决ABA问题 ==============
初始账户余额: 100元, 版本号: 0[转账线程] 读取余额: 100元, 版本: 0
[转账线程] 开始处理转账...
0
[ABA线程] 读取余额: 100元, 版本: 0
[ABA线程] 修改余额为50元: 成功, 新版本: 1
当前余额: 50[ABA线程] 读取余额: 50元, 版本: 1
[ABA线程] 恢复余额为100元: 成功, 新版本: 2
当前余额: 100[转账线程] 转账处理完成,尝试更新账户===== 转账操作结果 =====
操作结果: 失败
预期版本: 0, 实际版本: 2
预期余额: 100元, 当前余额: 100=====================最终账户余额: 100元, 版本号: 2
============== 演示结束 ==============Process finished with exit code 0
http://www.dtcms.com/a/325040.html

相关文章:

  • 基于python/django框架的车型识别系统
  • 复现论文《基于Retinex理论和深度学习的低照度图像增强算法研究》
  • 问津集 #4:The Five-Minute Rule for the Cloud: Caching in Analytics Systems
  • windows运维
  • SF-CPI-SAP问题收集24:集成地址信息的村里字段无法页面显示问题
  • ECharts 的理解和简单应用笔记
  • 【无标题】消息队列(Message Queue)是一种**进程间通信(IPC)机制
  • 深度学习-卷积神经网络-AlexNet
  • index.d.ts 是什么?作用 + 怎么生成?
  • 糖果大冒险:公平分发的智慧挑战
  • Stagewise使用指南:从项目集成到效能跃迁的深度解析
  • 【算法题】:和为N的连续正数序列
  • AI大模型-提示词工程
  • 01 词法分析陷阱:C编程中的符号误解
  • 深度解析 Spring Boot 循环依赖:原理、源码与解决方案
  • PhotoDirector 安卓版:功能强大的照片编辑与美化应用
  • TypeScript中的type和interface的区别是什么?
  • Shell脚本-数组定义
  • OpenEnler等Linux系统中安装git工具的方法
  • DDR中的POD与ODT
  • 分布式事务原理(高并发系统下的数据一致性保障)
  • 一、线性规划
  • 免费数字人API开发方案
  • 高精度计算+快速幂算法
  • 【算法题】:斐波那契数列
  • 【langchain】如何给langchain提issue和提pull request?
  • SpringIoc 实践和应用--XML配置
  • 数据结构-deque(双端队列)和queue(队列)区别
  • Flask多进程数据库访问问题详解
  • spring全家桶使用教程