当前位置: 首页 > 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.lryc.cn/news/616209.html

相关文章:

  • QT常用控件三
  • 浏览器CEFSharp88+X86+win7 之js交互开启(五)
  • 深入理解C语言一维数组的本质:数组名、指针常量与访问细节
  • 女子试穿4条裤子留下血渍赔50元引争议:消费责任边界在哪?
  • 无须炮解,打开即是Pro版
  • (LeetCode 每日一题) 869. 重新排序得到 2 的幂 (哈希表+枚举)
  • Python中随机化列表元素的详细方法
  • LintCode第604题-滑动窗口内数的和
  • DAY36打卡
  • 自创论述类文本阅读:论温泉
  • ubuntu 安装内核模块驱动 DKMS 介绍
  • 基于Ubuntu20.04的环境,编译QT5.15.17源码
  • ubuntu22.04+samba
  • 正则表达式常用语法参考
  • 零基础学Java第三讲---运算符
  • CSS优先级、HTTP响应状态码
  • ​Microsoft Store 离线下载软件
  • Unity笔记(四)——Camera、碰撞检测函数、刚体加力、音频
  • 电脑使用“碎片整理”程序的作用
  • Java I/O 流:从字节流到 NIO 的进化与应用
  • idea中使用maven造成每次都打印日志
  • IDEA官网下载及其他版本软件下载地址
  • Ubuntu 安装 Elasticsearch
  • 【0基础PS】PS工具详解--缩放工具
  • 【python】import与include的区别
  • 运维学习Day20——MariaDB数据库管理
  • 生产环境中Spring Cloud Sleuth与Zipkin分布式链路追踪实战经验分享
  • LeetCode_哈希表
  • 【代码随想录day 16】 力扣 112. 路径总和
  • Java学习第一百二十三部分——HTTP/HTTPS