热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

2.原子

在运用CAS做Lock-Free操作中有一个经典的ABA问题:线程1准备用CAS将变量的由A替换为B,在此之前,线程2将变量的由A替换为C,又由C替换为A,然后线程1执行CAS时发现变量的仍然为A,所以CAS成功。但实际上这时的现场已经和最初不同了,尽管CAS成功,但可能存

在运用CAS做Lock-Free操作中有一个经典的ABA问题: 线程1准备用CAS将变量的由A替换为B,在此之前,线程2将变量的由A替换为C,又由C替换为A,然后线程1执行CAS时发现变量的仍然为A,所以CAS成功。但实际上这时的现场已经和最初不同了,尽管CAS成功,但可能存

在运用CAS做Lock-Free操作中有一个经典的ABA问题:

线程1准备用CAS将变量的值由A替换为B,在此之前,线程2将变量的值由A替换为C,又由C替换为A,然后线程1执行CAS时发现变量的值仍然为A,所以CAS成功。但实际上这时的现场已经和最初不同了,尽管CAS成功,但可能存在潜藏的问题,例如下面的例子:


现有一个用单向链表实现的堆栈,栈顶为A,这时线程T1已经知道A.next为B,然后希望用CAS将栈顶替换为B:

head.compareAndSet(A,B);

在T1执行上面这条指令之前,线程T2介入,将A、B出栈,再pushD、C、A,此时堆栈结构如下图,而对象B此时处于游离状态:


此时轮到线程T1执行CAS操作,检测发现栈顶仍为A,所以CAS成功,栈顶变为B,但实际上B.next为null,所以此时的情况变为:


其中堆栈中只有B一个元素,C和D组成的链表不再存在于堆栈中,平白无故就把C、D丢掉了。

以上就是由于ABA问题带来的隐患,各种乐观锁的实现中通常都会用版本戳version来对记录或对象标记,避免并发操作带来的问题,在Java中,AtomicStampedReference也实现了这个作用,它通过包装[E,Integer]的元组来对对象标记版本戳stamp,从而避免ABA问题,例如下面的代码分别用AtomicInteger和AtomicStampedReference来对初始值为100的原子整型变量进行更新,AtomicInteger会成功执行CAS操作,而加上版本戳的AtomicStampedReference对于ABA问题会执行CAS失败:

public class Test {

	private static AtomicInteger atomicInt = new AtomicInteger(100);
	private static AtomicStampedReference atomicStampedRef = new AtomicStampedReference(
			100, 0);
	public static void main(String[] args) throws InterruptedException {
		Thread intT1 = new Thread(new Runnable() {
			@Override
			public void run() {
				atomicInt.compareAndSet(100, 101);
				atomicInt.compareAndSet(101, 100);
			}
		});

		Thread intT2 = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					TimeUnit.SECONDS.sleep(1);
				} catch (InterruptedException e) {
				}
				boolean c3 = atomicInt.compareAndSet(100, 101);
				System.out.println(c3); // true
			}
		});
		intT1.start();
		intT2.start();
		intT1.join();
		intT2.join();
		Thread refT1 = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					TimeUnit.SECONDS.sleep(1);
				} catch (InterruptedException e) {

				}
				atomicStampedRef.compareAndSet(100, 101,
						atomicStampedRef.getStamp(),
						atomicStampedRef.getStamp() + 1);

				atomicStampedRef.compareAndSet(101, 100,
						atomicStampedRef.getStamp(),
						atomicStampedRef.getStamp() + 1);

			}
		});

		Thread refT2 = new Thread(new Runnable() {
			@Override
			public void run() {
				int stamp = atomicStampedRef.getStamp();
				try {
					TimeUnit.SECONDS.sleep(2);
				} catch (InterruptedException e) {
				}
				boolean c3 = atomicStampedRef.compareAndSet(100, 101, stamp,
						stamp + 1);
				System.out.println(c3); // false
			}

		});
		refT1.start();
		refT2.start();
	}

}

推荐阅读
  • 探索新一代API文档工具,告别Swagger的繁琐
    对于后端开发者而言,编写和维护API文档既繁琐又不可或缺。本文将介绍一款全新的API文档工具,帮助团队更高效地协作,简化API文档生成流程。 ... [详细]
  • 实现自定义组件的多值v-model双向绑定
    探讨如何在自定义组件中实现多个输入框与父组件数据的动态双向绑定,确保组件内部多个值的变化能实时反映到父组件的数据中。 ... [详细]
  • 鼠标悬停出现提示信息怎么做
    概述–提示:指启示,提起注意或给予提醒和解释。在excel中会经常用到给某个格子增加提醒信息,比如金额提示输入数值或最大长度值等等。设置方式也有多种,简单的,仅为单元格插入批注就可 ... [详细]
  • 精致小屏灰色风格苹果CMS v10模板,支持DIY主题管理系统
    探索一款专为影视站设计的苹果CMS v10模板,具备强大的主题管理系统和500多个设置项,无需二次开发即可轻松配置。下载地址:https://www.mytheme.cn/maccms/244.html,演示地址:http://demo.mytheme.cn/index.php?id=244。 ... [详细]
  • 本文详细探讨了如何通过分析单个或多个线程在瓶颈情况下的表现,来了解处理器资源的消耗。无论是单进程还是多进程环境,监控关键指标如线程数量、占用时间及调度优先级等,有助于揭示潜在的性能问题。 ... [详细]
  • 使用Powershell Studio快速构建GUI应用程序
    本文介绍了如何利用Powershell Studio创建功能强大的可视化界面。相较于传统的开发工具,Powershell Studio提供了更为简便和高效的开发体验,尤其适合需要快速构建图形用户界面(GUI)的场景。 ... [详细]
  • 本文详细介绍了PHP中的多条件分支结构,包括if、elseif和else语句的使用方法。通过具体示例,解释了如何根据不同的条件执行相应的代码块,并确保每个条件只能触发一次。 ... [详细]
  • 气象对比分析
    本文探讨了不同地区和时间段的天气模式,通过详细的图表和数据分析,揭示了气候变化的趋势及其对环境和社会的影响。 ... [详细]
  • 使用PHP实现网站访客计数器的完整指南
    本文详细介绍了如何利用PHP构建一个简易的网站访客统计系统。通过具体的代码示例和详细的解释,帮助开发者理解和实现这一功能,适用于初学者和有一定经验的开发人员。 ... [详细]
  • 本文详细介绍了在 Windows 7 系统中配置 Nginx 1.10.3 和 PHP 7.1.1 NTS 的步骤,包括修改 PHP 配置文件、处理依赖项以及创建批处理脚本启动和停止服务。重点解释了如何解决常见的运行时错误。 ... [详细]
  • 在PHP后端开发中遇到一个难题:通过第三方类文件发送短信功能返回的JSON字符串无法解析。本文将探讨可能的原因并提供解决方案。 ... [详细]
  • 剑网3藏剑技能键盘配置与实战技巧
    本文详细介绍了《剑网3》中藏剑门派的技能键盘配置方法,以及在PVE和PVP中的具体使用技巧,帮助玩家更好地掌握藏剑的操作。 ... [详细]
  • 探讨 HDU 1536 题目,即 S-Nim 游戏的博弈策略。通过 SG 函数分析游戏胜负的关键,并介绍如何编程实现解决方案。 ... [详细]
  • 优化网页加载速度:JavaScript 实现图片延迟加载
    本文介绍如何使用 JavaScript 实现图片延迟加载,从而显著提升网页的加载速度和用户体验。 ... [详细]
  • 本文详细介绍了一种通过MySQL弱口令漏洞在Windows操作系统上获取SYSTEM权限的方法。该方法涉及使用自定义UDF DLL文件来执行任意命令,从而实现对远程服务器的完全控制。 ... [详细]
author-avatar
仙走壹步
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有