AtomicReference和AtomicStampedReference
一、AtomicReference
通过volatile和Unsafe提供的CAS函数实现原子操作。 自旋+CAS的无锁操作保证共享变量的线程安全
- value是volatile类型,这保证了:当某线程修改value的值时,其他线程看到的value的值都是最新的值,即修改之后的volatile的值
- 通过CAS设置value。这保证了:某线程池通过CAS函数(如compareAndSet函数)设置value时,它的操作时原子性的,即线程在操作vu略时不会被中断。
但是CAS操作可能存在ABA问题。AtomicStampedReference的出现就是为了解决这问题
备注:ABA问题:原始值为A,某个线程修改为B,另一个线程又修改为A,当第三个线程访问时,获取的值依然是A,认为该值没有被修改过。
注意:如下代码是线程不安全的
//先获取原始值
Integer oldValue = atomicReference.get();
//根据原始值比较进行修改
atomicReference.compareAndSet(oldValue,oldValue+);
若要保证线程安全,需要加锁(Lock或者synchronized)
Lock lock = new ReentrantLock();
...
lock.lock();
Integer oldValue = atomicReference.get();
atomicReference.compareAndSet(oldValue,oldValue+);
lock.unlock();
也就是说对于AtomicXX类,单个方法是原子性的,但是同时调用多个方法则不是原子性的,需要加锁实现线程安全。
二、AtomicStampedReference
AtomicStampedReference它内部不仅维护了对象值,还维护了一个时间戳(我这里把它称为时间戳,实际上它可以是任何一个整数,它使用整数来表示状态值)。当AtomicStampedReference对应的数值被修改时,除了更新数据本身外,还必须要更新时间戳。当AtomicStampedReference设置对象值时,对象值以及时间戳都必须满足期望值,写入才会成功。因此,即使对象值被反复读写,写回原值,只要时间戳发生变化,就能防止不恰当的写入。
举个栗子
AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference(0,1);
lock.lock();
Integer oldValue = atomicStampedReference.getReference();//
int stamp = atomicStampedReference.getStamp();//
atomicStampedReference.compareAndSet(oldValue,oldValue+1, stamp,stamp+1);
lock.unlock();
System.out.println(atomicStampedReference.getReference());//
System.out.println(atomicStampedReference.getStamp());//
AtomicReference和AtomicStampedReference的更多相关文章
- AtomicReference,AtomicStampedReference与AtomicMarkableReference的区别
AtomicReference 通过volatile和Unsafe提供的CAS函数实现原子操作. 自旋+CAS的无锁操作保证共享变量的线程安全 value是volatile类型,这保证了:当某线程修改 ...
- 4.4.4 无锁的对象引用:AtomicReference和AtomicStampedReference
AtomicReference 这个类和AtomicInteger非常类似,只是AtomicReference对应普通的对象引用,而AtomicInteger 它是对整数的封装,它的方法如下 对wea ...
- AtomicReference、AtomicStampedReference 和 AtomicMarkableReference
这三个都是自 JDK1.5 开始加入到 java.util.concurrent.atomic 下面的.他们都可以在 lock-free 的情况下以原子的方式更新对象引用. 一.AtomicRefer ...
- CAS导致的ABA问题及解决:时间戳原子引用AtomicReference、AtomicStampedReference
1.CAS导致ABA问题: CAS算法实现一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并交换,那么在这个时间差中会导致数据的变化. 比如:线程1从内存位置V中取出A,这时线程2也从V中取出A ...
- Java中Atomic包的实现原理及应用
1. 同步问题的提出 假设我们使用一个双核处理器执行A和B两个线程,核1执行A线程,而核2执行B线程,这两个线程现在都要对名为obj的对象的成员变量i进行加1操作,假设i的初始值为0,理论上两个线程运 ...
- Java多线程:CAS与java.util.concurrent.atomic
锁的几种概念 悲观锁 总是假设最坏的情况,每次获取数据都认为别人会修改,所以拿数据时会上锁,一直到释放锁不允许其他线程修改数据.Java中如synchronized和reentrantLock就是这种 ...
- java多线程(六)线程控制类
1. 多线程控制类 为了保证多线程的三个特性,Java引入了很多线程控制机制,下面介绍其中常用的几种: l ThreadLocal l 原子类 l Lock类 l Volatile关键字 ...
- DLC双端锁,CAS,ABA问题
一.什么是DLC双端锁?有什么用处? 为了解决在多线程模式下,高并发的环境中,唯一确保单例模式只能生成一个实例 多线程环境中,单例模式会因为指令重排和线程竞争的原因会出现多个对象 public cla ...
- 【Java并发工具类】原子类
前言 为保证计数器中count=+1的原子性,我们在前面使用的都是synchronized互斥锁方案,加锁独占访问的方式未免太过霸道,于是我们来介绍另一种解决原子性问题的无锁方案:原子变量.在正式介绍 ...
随机推荐
- Win7下使用TortoiseGit设置保存密码
1. 打开 TortoiseGit 设置,编辑 .gitconfig 文件,如图: 2. 添加下面两行配置,如图: [credential] helper = store 3. 保存退出即可
- 配置文件pytest.ini
前言 pytest配置文件可以改变pytest的运行方式,它是一个固定的文件pytest.ini文件,读取配置信息,按指定的方式去运行. ini配置文件 pytest里面有些文件是非test文件 py ...
- Selenium学习之==>Switch与SelectApi接口详解
Switch 我们在UI自动化测试时,总会出现新建一个tab页面.弹出一个浏览器级别的弹框或者是出现一个iframe标签,这时我们用WebDriver提供的Api接口就无法处理这些情况了.需要用到Se ...
- FreeMarker开发-数据模型
FreeMarker用于处理模板的数据模型是哈希表,也就是一个树状结构的name-value对.如下: (root)|+- string="string"| +- map| || ...
- django连接和游标
连接和游标主要实现 PEP 249中描述的Python DB API标准——除非它涉及到事务处理. 如果你不熟悉Python DB-API,注意cursor.execute()中的SQL语句使用占位符 ...
- MySQL学习-MySQL内置功能_索引与慢查询
1.索引基础 1.1 介绍 (1.)为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂 ...
- mysql源码包安装
一.准备编译环境 # yum -y install ncurses ncurses-devel openssl-devel bison gcc gcc-c++ make cmake # wget ht ...
- 用seaborn对数据可视化
以下用sns作为seaborn的别名 1.seaborn整体布局设置 sns.set_syle()函数设置图的风格,传入的参数可以是"darkgrid", "whiteg ...
- 【Qt开发】V4L2 API详解 Buffer的准备和数据读取
前面主要介绍的是:V4L2 的一些设置接口,如亮度,饱和度,曝光时间,帧数,增益,白平衡等.今天看看V4L2 得到数据的几个关键ioctl,Buffer的申请和数据的抓取. 1. 初始化 Memory ...
- Diango路由映射FBV和CBV
django中请求处理方式有2种:FBV(function base views) 和 CBV(class base views),换言之就是一种用函数处理请求,一种用类处理请求. FBV # url ...