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 ...
随机推荐
- 简单的编写java的helloWord
那么在上一章章节 http://www.cnblogs.com/langjunnan/p/6814641.html 我们简单的俩了解了一下什么是java和配置编写java的环境,本章呢我们学习如何编写 ...
- H5系列一、静态页面总结
1.img父标签设置高度,如果容器没有设置高度的话,图片会默认把容器底部撑大几像素 -- 大概3px,给容器设置高度. 2.input标记换行后默认有一个间隙,设置float属性.input标记默认还 ...
- ARC中__bridge, __bridge__transfer, __bridge_retained 关系
总结于 IOS Tuturial 中 ARC两章,详细在dropbox pdf 文档. Toll-Free Bridging 当你在 Objective-C 和 Core Foundation 对象之 ...
- django学习笔记 多文件上传
习惯了flask 再用django 还是不太习惯 好麻烦 配置文件也忒多了 不过还是要学的 之前只能一个一个文件长传,这次试试多个文件 不适用django的forms创建表单 直接在html中使用 ...
- 个人项目作业(wc.exe)
1.GitHub项目地址 https://github.com/QiuBin666/WC 项目介绍: 题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行 ...
- aireplay包注入攻击
reaver爆破WPS PIN码: airodump-ng wlan0 reaver -i wlan0 -b D0:76:E7:51:2A:78 -vv macchanger更改MAC地址: ma ...
- 性能测试进阶:(一)性能测试工具Locust
An open source load testing tool. 一个开源性能测试工具. define user behaviour with python code, and swarm your ...
- js 面向对象 打气球小游戏
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Gorm 预加载及输出处理(二)- 查询输出处理
上一篇<Gorm 预加载及输出处理(一)- 预加载应用>中留下的三个问题: 如何自定义输出结构,只输出指定字段? 如何自定义字段名,并去掉空值字段? 如何自定义时间格式? 这一篇先解决前两 ...
- 项目部署Django+celery+redis
celery介绍 1.celery应用举例 1.Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以 ...