CAS / ABA

标签(空格分隔): 操作系统


1. CAS 解决 Volatile 不保证原子性的问题

/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
} public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5;
}

Volatile不保证原子性的解决方案, 在其中我们可以看到我们通过atomicInteger.getAndIncrement(), 获取值并且将其+1, 重点在于this.compareAndSwapInt(var1, var2, var5, var5 + var4) 通过乐观锁的方法, 相当于实现了原子性的操作.

2. CAS 导致的 ABA 问题解决

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference; /**
* CAS会导致ABA问题:
* CAS算法实现一个重要前提需要取出内存中某时刻的数据并且在当下时刻进行比较并替换(Compare And Set), 那么在这个时间差的时候可能会导致数据的变化.
* 比如: 一个线程one从内存位置中V中取出A, 这个时候另一个线程two也从内存中取出A. 此时线程one和two都持有位置V中A的备份, 在这个时候two将A->B->A 并写入主存当中.
* 线程one去进行CAS操作的时候, 发现内存中仍然是A, 然后线程one操作成功.
*
* 这个问题主要看线程two对中间操作对 线程one有影响没, 如果有影响的话. 需要解决一下CAS问题.
*/
public class Test { private static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1); public static void main(String[] args) {
/* ABA问题产生实例 Start */
new Thread(()->{
atomicReference.compareAndSet(100,101);
atomicReference.compareAndSet(101,100);
},"t1").start(); new Thread(()->{
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicReference.compareAndSet(100, 2019)+"\t"+atomicReference.get());
}).start();
/* ABA问题产生实例 End */ /* ABA问题解决实例 Start */
new Thread(() -> {
int stamp = atomicStampedReference.getStamp();
System.out.println(Thread.currentThread().getName() + "\t 第一次版本号 : " + atomicStampedReference.getStamp());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
atomicStampedReference.compareAndSet(100, 101, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
System.out.println(Thread.currentThread().getName() + "\t 第二次版本号 : " + atomicStampedReference.getStamp());
atomicStampedReference.compareAndSet(101, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
System.out.println(Thread.currentThread().getName() + "\t 第三次版本号 : " + atomicStampedReference.getStamp());
}, "t3").start(); new Thread(() -> {
int stamp = atomicStampedReference.getStamp();
System.out.println(Thread.currentThread().getName() + "\t 第一次版本号 : " + atomicStampedReference.getStamp());
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("是否修改成功: " + atomicStampedReference.compareAndSet(100, 2019, 1, atomicStampedReference.getStamp() + 1) + "\t 当前的stamp值: " + atomicStampedReference.getStamp());
System.out.println("当前最新值: " + atomicStampedReference.getReference());
}, "t4").start();
/* ABA问题 解决实例 End */ }
}

CAS / ABA的更多相关文章

  1. JDK对CAS ABA问题解决-AtomicMarkableReference和AtomicStampedReference

    我们知道AtomicInteger和AtomicLong的原子操作,但是在这两个类在CAS操作的时候会遇到ABA问题,可能大家会疑问什么是ABA问题呢,请待我细细道来: ABA问题:简单讲就是多线程环 ...

  2. Java CAS ABA问题发生的场景分析

    提到了CAS操作存在问题,就是在CAS之前A变成B又变回A,CAS还是能够设置成功的,什么场景下会出现这个问题呢?查了一些资料,发现在下面的两种情况下会出现ABA问题. 1.A最开始的内存地址是X,然 ...

  3. Java并发编程原理与实战四十三:CAS ---- ABA问题

    CAS(Compare And Swap)导致的ABA问题 问题描述 多线程情况下,每个线程使用CAS操作欲将数据A修改成B,当然我们只希望只有一个线程能够正确的修改数据,并且只修改一次.当并发的时候 ...

  4. CAS ABA问题

    java.util.concurrent包的最底层基础CAS技术,原理很简单. CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B.当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什 ...

  5. CAS -- ABA问题的解决方案

    我们现在来说什么是ABA问题.假设内存中有一个值为A的变量,存储在地址V中. 此时有三个线程想使用CAS的方式更新这个变量的值,每个线程的执行时间有略微偏差.线程1和线程2已经获取当前值,线程3还未获 ...

  6. DLC双端锁,CAS,ABA问题

    一.什么是DLC双端锁?有什么用处? 为了解决在多线程模式下,高并发的环境中,唯一确保单例模式只能生成一个实例 多线程环境中,单例模式会因为指令重排和线程竞争的原因会出现多个对象 public cla ...

  7. 一篇文章快速搞懂 Atomic(原子整数/CAS/ABA/原子引用/原子数组/LongAdder)

    前言 相信大部分开发人员,或多或少都看过或写过并发编程的代码.并发关键字除了Synchronized,还有另一大分支Atomic.如果大家没听过没用过先看基础篇,如果听过用过,请滑至底部看进阶篇,深入 ...

  8. 沉淀再出发:java中的CAS和ABA问题整理

    沉淀再出发:java中的CAS和ABA问题整理 一.前言 在多并发程序设计之中,我们不得不面对并发.互斥.竞争.死锁.资源抢占等等问题,归根到底就是读写的问题,有了读写才有了增删改查,才有了所有的一切 ...

  9. 第47天打卡学习(单例模式 深入了解CAS 原子引用 各种锁的理解)

    18彻底玩转 单例模式 饿汉式 DCL懒汉模式 探究! 饿汉式  package com.kuang.single; //饿汉式单例 //单例模式重要思想是构造器私有 public class Hun ...

随机推荐

  1. Serializable详解(1):代码验证Java序列化与反序列化

    说明:本文为Serializable详解(1),最后两段内容在翻译上出现歧义(暂时未翻译),将在后续的Serializable(2)文中补充. 介绍:本文根据JDK英文文档翻译而成,本译文并非完全按照 ...

  2. JS模块规范:AMD,CMD,CommonJS

    浅析JS模块规范 随着JS模块化编程的发展,处理模块之间的依赖关系成为了维护的关键. AMD,CMD,CommonJS是目前最常用的三种模块化书写规范. CommonJS CommonJS规范是诞生比 ...

  3. 如何搭建自己的SpringBoot源码调试环境?--SpringBoot源码(一)

    1 前言 这是SpringBoot2.1源码分析专题的第一篇文章,主要讲如何来搭建我们的源码阅读调试环境.如果有经验的小伙伴们可以略过此篇文章. 2 环境安装要求 IntelliJ IDEA JDK1 ...

  4. js 统计一个字符串中出现的字符最多的字符

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. MVVM相关框架

    Caliburn.Micro PropertyChanged.Fody Prism MVVMLight (未完)

  6. ExifPro Mod 3.0 64位绿色中文版

    EXIFPro 是一个优秀的图像查看, 处理及管理工具, 使用 VC++ 开发, 小巧快速, 支持查看丰富的 EXIF 信息, 非常适用于查看您的 RAW 数字照片和其他常规图像.EXIFPro V1 ...

  7. 最详细的 Spring Boot 多模块开发与排坑指南

    创建项目 创建一个 SpringBoot 项目非常的简单,简单到这里根本不用再提.你可以在使用 IDEA 新建项目时直接选择 Spring Initlalize 创建一个 Spring Boot 项目 ...

  8. 环境篇:Docker

    环境篇:Docker www.docker.com Docker 是什么? Docker 是一个开源的应用容器引擎,基于Go语言并遵从Apache协议的开源,让开发者可以打包他们的应用以及依赖包到一个 ...

  9. 安装sql server 2005时出现“安装汇编”错误的解决办法

    今天安装sql server 2005 management studio到最后步骤的时候报“安装汇编”错误,卸载重装的几遍还是不行,最后将net framework 3.5删除后,终于安装成功了.

  10. 洛谷 P5176 公约数 题解

    原题链接 我天哪 大大的庆祝一下: 数论黑题 \(T1\) 达成! 激动地不行 记住套路:乱推 \(\gcd\),欧拉筛模板,然后乱换元,乱换式子,完了整除分块,欧拉筛和前缀和就解决了! \[\sum ...