CAS / ABA
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的更多相关文章
- JDK对CAS ABA问题解决-AtomicMarkableReference和AtomicStampedReference
我们知道AtomicInteger和AtomicLong的原子操作,但是在这两个类在CAS操作的时候会遇到ABA问题,可能大家会疑问什么是ABA问题呢,请待我细细道来: ABA问题:简单讲就是多线程环 ...
- Java CAS ABA问题发生的场景分析
提到了CAS操作存在问题,就是在CAS之前A变成B又变回A,CAS还是能够设置成功的,什么场景下会出现这个问题呢?查了一些资料,发现在下面的两种情况下会出现ABA问题. 1.A最开始的内存地址是X,然 ...
- Java并发编程原理与实战四十三:CAS ---- ABA问题
CAS(Compare And Swap)导致的ABA问题 问题描述 多线程情况下,每个线程使用CAS操作欲将数据A修改成B,当然我们只希望只有一个线程能够正确的修改数据,并且只修改一次.当并发的时候 ...
- CAS ABA问题
java.util.concurrent包的最底层基础CAS技术,原理很简单. CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B.当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什 ...
- CAS -- ABA问题的解决方案
我们现在来说什么是ABA问题.假设内存中有一个值为A的变量,存储在地址V中. 此时有三个线程想使用CAS的方式更新这个变量的值,每个线程的执行时间有略微偏差.线程1和线程2已经获取当前值,线程3还未获 ...
- DLC双端锁,CAS,ABA问题
一.什么是DLC双端锁?有什么用处? 为了解决在多线程模式下,高并发的环境中,唯一确保单例模式只能生成一个实例 多线程环境中,单例模式会因为指令重排和线程竞争的原因会出现多个对象 public cla ...
- 一篇文章快速搞懂 Atomic(原子整数/CAS/ABA/原子引用/原子数组/LongAdder)
前言 相信大部分开发人员,或多或少都看过或写过并发编程的代码.并发关键字除了Synchronized,还有另一大分支Atomic.如果大家没听过没用过先看基础篇,如果听过用过,请滑至底部看进阶篇,深入 ...
- 沉淀再出发:java中的CAS和ABA问题整理
沉淀再出发:java中的CAS和ABA问题整理 一.前言 在多并发程序设计之中,我们不得不面对并发.互斥.竞争.死锁.资源抢占等等问题,归根到底就是读写的问题,有了读写才有了增删改查,才有了所有的一切 ...
- 第47天打卡学习(单例模式 深入了解CAS 原子引用 各种锁的理解)
18彻底玩转 单例模式 饿汉式 DCL懒汉模式 探究! 饿汉式 package com.kuang.single; //饿汉式单例 //单例模式重要思想是构造器私有 public class Hun ...
随机推荐
- oracle的wm_concat函数实现行转列
有以下数据 deptname phone username isboss 部门A 电话1 员工A 0 部门A 电话1 领导A 1 部门B 电话2 员工B 0 部门B 电话2 员工C 0 部门B 电话2 ...
- Eureka停更了?试试Zookpper和Consul
在Spring Cloud Netflix中使用Eureak作为注册中心,但是Eureka2.0停止更新,Eureka1.0 进入了维护状态.就像win7一样,同样可以用,但是官方对于新出现的问题并不 ...
- Redis02——Redis内存数据如何保存到磁盘
在前一篇文章中,已经介绍了Redis的基础数据结构,这篇文章将继续介绍Redis的持久化原理. 简介 众所周知Redis的所有数据都存在于内存之中,这就会存在因内存问题而导致的数据丢失,为了避免这一问 ...
- 对时间进行操作 加减 XXX天
date:要操作的时间目标 days: 要加减的天数时间 addDate: function(date, days) { if (date == '') { return '' }; if (days ...
- Hadoop集群搭建(六)~安装JDK
前面集群的准备工作都做完了,本篇记录安装JDK,版本位1.8 1,在opt目录下创建software和module文件夹:software用来放安装包,module为安装目录 2,把JDK和hadoo ...
- OneNote代码高亮
向OneNote 2016安装NoteHighlight 下载.msi 文件,下载链接 下载之前查看自己的电脑上安装的OneNote版本以及位数(32-64) 查看方法:文件->选项->关 ...
- Tomcat 启动过滤器异常
严重 [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.StandardContext.filterStart 启动过滤器异常 ja ...
- SQL的分类使用(增删改查)
1.SQL的分类使用(*代表重点的程度) DDL ** (Data Definition Language)数据库定义语言 用来定义数据库对象: 库 表 列 等 DCL (D ...
- 常用的API和基础算法
和数学相关 1,java.lang.Math类 abs(x):求绝对值 sqrt(x):求平方根 pow(x,y):求x的y次方 ceil(x):向上取整 floor(x):向下取整 round(x) ...
- (2)Windows PowerShell使用
什么是PowerShell: Windows PowerShell 是一种命令行外壳程序和脚本环境,使命令行用户和脚本编写者可以利用 .NET Framework 的强大功能.PowerShell是命 ...