这三个都是自 JDK1.5 开始加入到 java.util.concurrent.atomic 下面的。他们都可以在 lock-free 的情况下以原子的方式更新对象引用。

一、AtomicReference

以原子方式更新对象引用。

static class User {
private int age; public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public User(int age) {
this.age = age;
}
} public static void main(String[] args) {
User user1 = new User(10);
User user2 = new User(20); AtomicReference<User> atomicReference = new AtomicReference<>(user1);
System.out.println(atomicReference.get().getAge()); atomicReference.compareAndSet(user1, user2);
System.out.println(atomicReference.get().getAge());
}

二、AtomicStampedReference

解决了 AtomicReference 中 CAS 操作存在的 ABA 问题。

public static void main(String[] args) {
User user1 = new User(10);
User user2 = new User(20); AtomicStampedReference<User> stampedReference = new AtomicStampedReference<>(user1, 1); int[] stamp = new int[1];
// 获取引用对象和对应的版本号
System.out.println(stampedReference.get(stamp).getAge()); int oldStamp = stamp[0];
// 预期引用,新引用,预期版本号,新版本号
stampedReference.compareAndSet(user1, user2, oldStamp, 2); System.out.println(stampedReference.get(stamp).getAge());
}

內部定义了一个 Pair 对象,相当于给引用加了一个版本号

public class AtomicStampedReference<V> {

    private static class Pair<T> {
final T reference;
final int stamp;
private Pair(T reference, int stamp) {
this.reference = reference;
this.stamp = stamp;
}
static <T> Pair<T> of(T reference, int stamp) {
return new Pair<T>(reference, stamp);
}
} private volatile Pair<V> pair; public AtomicStampedReference(V initialRef, int initialStamp) {
pair = Pair.of(initialRef, initialStamp);
}

替换时的逻辑,当引用和版本号都相同时才使用 CAS 替换

public boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) {
Pair<V> current = pair;
return expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));
} private boolean casPair(Pair<V> cmp, Pair<V> val) {
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
}

三、AtomicMarkableReference

相对于 AtomicStampedReference,有时候,我们并不关心引用变量更改了几次,只是单纯的关心是否更改过

public static void main(String[] args) {
User user1 = new User(10);
User user2 = new User(20); AtomicMarkableReference<User> stampedReference = new AtomicMarkableReference<>(user1, false); boolean[] stamp = new boolean[1];
// 获取引用对象和对应的状态
System.out.println(stampedReference.get(stamp).getAge()); boolean oldStamp = stamp[0];
// 预期引用,新引用,预期状态,新状态
stampedReference.compareAndSet(user1, user2, oldStamp, false); System.out.println(stampedReference.get(stamp).getAge());
}

内部和 AtomicStampedReference 一样

public class AtomicMarkableReference<V> {

    private static class Pair<T> {
final T reference;
final boolean mark;
private Pair(T reference, boolean mark) {
this.reference = reference;
this.mark = mark;
}
static <T> Pair<T> of(T reference, boolean mark) {
return new Pair<T>(reference, mark);
}
} private volatile Pair<V> pair; public AtomicMarkableReference(V initialRef, boolean initialMark) {
pair = Pair.of(initialRef, initialMark);
} public boolean compareAndSet(V expectedReference, V newReference, boolean expectedMark, boolean newMark) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
expectedMark == current.mark &&
((newReference == current.reference &&
newMark == current.mark) ||
casPair(current, Pair.of(newReference, newMark)));
} private boolean casPair(Pair<V> cmp, Pair<V> val) {
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
}

https://segmentfault.com/a/1190000015831791

AtomicReference、AtomicStampedReference 和 AtomicMarkableReference的更多相关文章

  1. ABA问题怎么解:AtomicStampedReference和AtomicMarkableReference

    本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 并发编程的基石--CAS机制这篇文章中介绍到CAS机制有 ...

  2. AtomicReference,AtomicStampedReference与AtomicMarkableReference的区别

    AtomicReference 通过volatile和Unsafe提供的CAS函数实现原子操作. 自旋+CAS的无锁操作保证共享变量的线程安全 value是volatile类型,这保证了:当某线程修改 ...

  3. AtomicStampedReference、AtomicMarkableReference 区别

    AtomicMarkableReference 描述的是更加简单的是与否的关系,它的定义就是将数据变换为true 或 false,通常ABA问题只有两种状态,AtomicMarkableReferen ...

  4. Java并发编程-总纲

    Java 原生支持并发,基本的底层同步包括:synchronized,用来标示一个方法(普通,静态)或者一个块需要同步执行(某一时刻,只允许一个线程在执行代码块).volatile,用来标识一个变量是 ...

  5. 非阻塞同步机制与CAS操作

    锁的劣势 Java在JDK1.5之前都是靠synchronized关键字保证同步的,这种通过使用一致的锁定协议来协调对共享状态的访问,可以确保无论哪个线程 持有守护变量的锁,都采用独占的方式来访问这些 ...

  6. 还在用Synchronized?Atomic你了解不?

    前言 只有光头才能变强 之前已经写过多线程相关的文章了,有兴趣的同学可以去了解一下: https://github.com/ZhongFuCheng3y/3y/blob/master/src/thre ...

  7. Java面试 32个核心必考点完全解析

    目录 课程预习 1.1 课程内容分为三个模块 1.2 换工作面临问题 1.3 课程特色 课时1:技术人职业发展路径 1.1 工程师发展路径 1.2 常见技术岗位划分 1.3 面试岗位选择 1.4 常见 ...

  8. 三、原子变量与CAS算法

    原子变量:jdk1.5 后 java.util.concurrent.atomic 包下提供了常用的原子变量: - AtomicBoolean - AtomicInteger - AtomicLong ...

  9. Java多线程并发编程一览笔录

    线程是什么? 线程是进程中独立运行的子任务. 创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runnable 接口的类.该 ...

随机推荐

  1. 前端通过url下载文件方法

    前端通过url下载文件方法 产生背景 浏览器通过url下载文件,当浏览器识别出资深能播放的资源文件,就不会走下载流程,会直接打开 解决方法 1.让后台转成请求的方式,输出文件流(如果想实现批量下载-因 ...

  2. 复选框已经有checked,但是页面没有选中效果(解决)

    原代码: $("#checked").click(function(){ $(".input[name="checked"]").attr( ...

  3. 阻塞IO和非阻塞IO

    1 TCP协议 每一个TCP通信的的socket的内核里面都会有一个发送缓冲区和接收缓冲区 发送端 : send 报文 -- TCP发送缓冲区 -- 接收端 :TCP接收缓冲区 -- receive ...

  4. JComboBox实现时间控件

    1.认识JComboBox控件 最近学习使用了JComboBox组件: 在学习使用了JList以及Jtree组件之后,对于使用JComboBox还是很轻松的. JcomboBox的其实也是由一个Mod ...

  5. python 之禅 又名 蛇宗三字经

    打开cmd 输入python回车 import this Beautiful is better than ugly. Explicit is better than implicit. Simple ...

  6. delphi xe5 fastreport4.14 中文很多时换行不正确

    用一般的frxMEMOview 中文换行是瞎换,缺少数据,换成frxrichview 即可, frxrichview 使用注意点 1).Delphi中文很多时换行不正确 2).要在窗体上拖一个frxr ...

  7. h5 特效

    地址:http://www.cnblogs.com/sun927/p/5842852.html 几个别人总结的css3炫酷效果,有需要直接拿来用即可,包括以下几个效果: 1.悬浮时放大 2.悬浮时转一 ...

  8. 洛谷P1462 通往奥格瑞玛的道路(SPFA+二分答案)

    题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛 题目描述 在艾泽拉斯, ...

  9. percona-toolkit主从同步整理(MySQL)

    前言:MYSQL主从同步架构是目前使用最多的数据库架构之一,尤其是负载比较大的网站,因此对于主从同步的管理也就显得非常重要.而数据作为软件的核心部分,对于其有效的管理显得更为重要.随着时间的推移,软件 ...

  10. visual studio 和visual studio code 的区别是什么?

    区别有三: 区别一:含义不一样. Visual Studio(简称VS)是美国微软公司的开发工具包系列产品,是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具.代码 ...