ABA问题_乐观锁aba引发的实际问题

ABA问题_乐观锁aba引发的实际问题ABA问题一.概述:二.什么是ABA问题?三.ABA问题的解决:原子引用:(存在ABA问题)带版本号的原子引用(解决ABA问题)一.概述:ABA问题是在多线程并发的情况下,发生的一种现象。上一次记录了有关CAS操作的一些知识,CAS通过比较内存中的一个数据是否是预期值,如果是就将它修改成新值,如果不是则进行自旋,重复比较的操作,直到某一刻内存值等于预期值再进行修改。而ABA问题则是在CAS操作中存在的一个经典问题,这个问题某些时候不会带来任何影响,某些时候却是影响很大的。二.什么是ABA问题?理解一

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

一.概述:

ABA问题是在多线程并发的情况下,发生的一种现象。上一次记录了有关CAS操作的一些知识,CAS通过比较内存中的一个数据是否是预期值,如果是就将它修改成新值,如果不是则进行自旋,重复比较的操作,直到某一刻内存值等于预期值再进行修改。而ABA问题则是在CAS操作中存在的一个经典问题,这个问题某些时候不会带来任何影响,某些时候却是影响很大的。

二.什么是ABA问题?

理解一:
当执行campare and swap会出现失败的情况。例如,一个线程先读取共享内存数据值A,随后因某种原因,线程暂时挂起,同时另一个线程临时将共享内存数据值先改为B,随后又改回为A。随后挂起线程恢复,并通过CAS比较,最终比较结果将会无变化。这样会通过检查,这就是ABA问题。 在CAS比较前会读取原始数据,随后进行原子CAS操作。这个间隙之间由于并发操作,最终可能会带来问题。
理解二
在这里插入图片描述

“ABA”问题:假设t1线程工作时间为10秒,t2线程工作时间为2秒,那么可能在A的工作期间,主内存中的共享变量 A已经被t2线程修改了多次,只是恰好最后一次修改的值是该变量的初始值,虽然用CAS判定出来的结果是期望值,但是却不是原来那个了=======》“狸猫换太子”
相当于是只关心共享变量的起始值和结束值,而不关心过程中共享变量是否被其他线程动过。
有些业务可能不需要关心中间过程,只要前后值一样就行,但是有些业务需求要求变量在中间过程不能被修改。

只靠CAS无法保证ABA问题,需要使用“原子引用”才能解决!!!!

三.ABA问题的解决:

原子引用:(存在ABA问题)

案列:

 package InterviewTest;

import java.util.concurrent.atomic.AtomicReference;

class User{ 
   
	 String name;
	 int age;
	 
	 public User(String name,int age) { 
   
		 this.name=name;
		 this.age=age;
	 }

	@Override
	public String toString() { 
   
		return "User [name=" + name + ", age=" + age + "]";
	}

	public String getName() { 
   
		return name;
	}

	public void setName(String name) { 
   
		this.name = name;
	}
	public int getAge() { 
   
		return age;
	}

	public void setAge(int age) { 
   
		this.age = age;
	}
 }
public class AtomicReferenceDemo { 
   
	public static void main(String[] args) { 
   
		User z3 = new User("z3",25);
		User li4 = new User("li4",25);
		AtomicReference<User> atomicReference  = new AtomicReference<>();
		atomicReference.set(z3);
		System.out.println(atomicReference);
		System.out.println(atomicReference.compareAndSet(z3, li4)+
							" "+atomicReference.get().toString());
		System.out.println(atomicReference.compareAndSet(li4, z3)+
				" "+atomicReference.get().toString());
	}
}

Jetbrains全家桶1年46,售后保障稳定

带版本号的原子引用(解决ABA问题)

AtomicStampedReference版本号原子引用:
案例:两种原子引用的对比


package InterviewTest;

import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

public class ABADemo { 
   
	
	
	static AtomicReference<Integer> atomicReference 
									= new AtomicReference<>(100);
	static AtomicStampedReference<Integer>  atomicStampedReference 
									= new AtomicStampedReference<>(100,1);
	
	
	public static void main(String[] args) { 
   
		
		System.out.println("************以下是ABA问题的产生**************");
		new Thread(()->{ 
   
			atomicReference.compareAndSet(100, 101);
			atomicReference.compareAndSet(101, 100);
		},"t1").start();
		
		new Thread(()->{ 
   
			try { 
   
				Thread.sleep(1000);
			} catch (InterruptedException e) { 
   
				e.printStackTrace();
			}
			
			System.out.println(atomicReference.compareAndSet(100, 2019)
					+" "+atomicReference.get());
		},"t2").start();
		
		
		try { 
   
			Thread.sleep(2000);
		} catch (InterruptedException e) { 
   
			e.printStackTrace();
		}
		
		System.out.println("************以下是ABA问题的解决**************");
		
		new Thread(()->{ 
   
			int stamp = atomicStampedReference.getStamp();
			System.out.println(Thread.currentThread().getName()
					+" "+" 第一次版本号:"+stamp);
			try { 
   
				Thread.sleep(1000);
			} catch (InterruptedException e) { 
   
				e.printStackTrace();
			}
			
			atomicStampedReference.compareAndSet(100, 
										101, 
										atomicStampedReference.getStamp(),
										atomicStampedReference.getStamp()+1);
			System.out.println(Thread.currentThread().getName()
					+" "+" 第2次版本号:"+atomicStampedReference.getStamp());
			atomicStampedReference.compareAndSet(101, 
					100, 
					atomicStampedReference.getStamp(),
					atomicStampedReference.getStamp()+1);
			System.out.println(Thread.currentThread().getName()
					+" "+" 第3次版本号:"+atomicStampedReference.getStamp());
			
		},"t3").start();
		
		new Thread(()->{ 
   
			int stamp = atomicStampedReference.getStamp();
			System.out.println(Thread.currentThread().getName()
					+" "+" 第一次版本号:"+stamp);
			try { 
   
				Thread.sleep(3000);
			} catch (InterruptedException e) { 
   
				e.printStackTrace();
			}
			
			boolean result =  atomicStampedReference.compareAndSet(
					100, 
					2019, 
					stamp, 
					stamp+1);
			System.out.println(Thread.currentThread().getName()+
					" 修改成功否:"+result+" 当前最新实际版本号:"
					+atomicStampedReference.getStamp());
			System.out.println(Thread.currentThread().getName()+
					" 当前实际最新值:"
					+atomicStampedReference.getReference());
			
		},"t4").start();
	}

}
************以下是ABA问题的产生**************
true   2019
************以下是ABA问题的解决**************
t3     第一次版本号:1
t4     第一次版本号:1
t3     第2次版本号:2
t3     第3次版本号:3
t4  修改成功否:false  当前最新实际版本号:3
t4  当前实际最新值:100

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/203708.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • u盘拒绝访问怎么解决win11_u盘无权限访问

    u盘拒绝访问怎么解决win11_u盘无权限访问使用U盘启动盘安装系统时需要用到U盘,但是当我们将U盘插上电脑,结果出现拒绝访问的情形,别说是使用U盘启动盘重装系统了,连U盘基础的文件存储功能都无法使用。当U盘出现拒绝访问怎么解决呢?就此问题,下面小编分享u盘拒绝访问没有权限的原因和解决方法。U盘出现拒绝访问怎么解决1、U盘问题1)鼠标右键单击U盘盘符,在右键菜单中点击属性。2)在弹出的属性窗口中点击“工具”选项卡,再点击“开始检查”按钮,如下图所示:3)接着勾选“自动修复文件系统错误”和“扫描并尝试恢复坏扇区”并点击“开始”按钮(1)4)

    2022年10月1日
    4
  • 关于HeartBleed漏洞的总结「建议收藏」

    关于HeartBleed漏洞的总结「建议收藏」一:前言HeartBleed漏洞又称为心脏出血漏洞,编号(CVE-2014-0160),产生原因:由于未能在memcpy()调用受害用户输入的内容作为长度参数之前正确进行边界检查。攻击者可以追踪OpenSSl所分配的64KB内存,将超出必要范围的字节信息复制到缓存当中,再返回缓存内容,这样一来,受害者的内存内容就会每次泄露64KB.简单来说,这就是OpenSSL缺陷造成的漏洞二:环境…

    2022年7月25日
    16
  • Tomcat启动:A fatal error has been detected by the Java Runtime Environment(JVM Crash分析及相关资料)

    Tomcat启动:A fatal error has been detected by the Java Runtime Environment(JVM Crash分析及相关资料)iLife s 博客 http blog csdn net fei 年 1 月 10 号注 今天更新代码之后 突然出现一个问题 Tomcat 启动时 总是会出现 jvmfatalerro 错误导致 tomcat 无法正常启动 以下是错误信息 Afatalerrorh

    2025年7月7日
    4
  • 内测体验:JetBrains面向未来的Fleet编辑器是什么+究竟怎样 使用初体验+与vsc对比

    内测体验:JetBrains面向未来的Fleet编辑器是什么+究竟怎样 使用初体验+与vsc对比引言上个月,我在看到某公众号推广后,作为热衷于先进技术、常年游历于各个软件公司内测组的用户自然是早早申请了内测。因为在申请时官网的公告是“我们也不知道新一代编辑器(Fleet)什么时候可以与大家见面”,因此我也没有过多在意。令人意外的是,昨天晚上22:09,我收到了来自JetBrains的邮件。此处点名一下GitHubCopilot项目,申请完了这么久还不给个信[手动旺柴]简介如果你实在不知道什么是JetBrains,那你也应该知道PyCharm,再次也要知道AndroidStudio。

    2022年6月7日
    58
  • mysql下载与安装教程_jdk下载与安装教程

    mysql下载与安装教程_jdk下载与安装教程MySQL下载和安装教程下载MySQL数据库可以访问官方网站:https://www.mysql.com/点击DOWNLOADS模块下的Community模块,进行下载或可访问网页:https://dev.mysql.com/downloads/mysql/直接下载MySQL社区服务版进入,选择MySQL的版本及主机目前最新版本是:MySQLCommunityServer8.0.27,点击下载点击后进入下一页面,该页面可注册MySQL账户,可登录MySQL账户,也可不进行注册,直接下

    2025年9月13日
    9
  • linux下安装tomcat配置环境变量

    linux下安装tomcat配置环境变量linux下安装tomcat,一定记得配置环境变量,在tomcat的bin目录通过vi命令打开catalina.sh,在catalina.sh中加入如下配置:exportTOMCAT_HOME=/usr/local/apache-tomcat-9.0.0.M26exportCATALINA_HOME=/usr/local/apache-tomcat-9.0.0.M26exportJRE_HOME=/usr/lib/jvm/jdk1.8.0_131/jreexportJAVA_HOME=/u

    2022年6月4日
    38

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号