这三个都是自 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. JavaScript随机验证码

    利用canvas制作一个随机验证码: 1.clearRect:context.clearRect(x,y,width,height);清空给定矩形内的指定像素 2.fillStyle:设置画笔的颜色 ...

  2. JavaScript 标准内置对象

    JavaScript 标准内置对象或称全局的对象(global objects)不要和 全局对象(global object)混淆.这里说的全局的对象是说在全局作用域里的对象,全局作用域包含了全局对象 ...

  3. 在线播放mp4

    在线播放mp4 1.准备好支持再网页上播放的mp4格式 AVC(h264) 格式的mp4 2.用ckplayer控制播放 (1)到ckplayer下载js.如:http://www.ckplayer. ...

  4. shiro系列三、ssm框架整合shiro实现权限控制

    shiro权限框架是一个非常优秀的框架,前面的几篇文章对shiro进行了非常详细的介绍和原理分析,那么接下来让我们开始在web项目中使用它(javase也能用shiro): 一.数据库表结构设计 二. ...

  5. shiro系列三、定义Realm

    自定义realm: /** * 认证和授权 */ @Component public class UserRealm extends AuthorizingRealm { @Autowired pri ...

  6. Hdu 4661 树上拓扑序计数

    #include <bits/stdc++.h> using namespace std; typedef long long ll; ; ; ; ], nxt[MAXM << ...

  7. 【转】高可用Redis(六):瑞士军刀之bitmap,HyperLoglog和GEO

    1.bitmap位图 1.1 bitmap位图的概念 首先来看一个例子,字符串big, 字母b的ASCII码为98,转换成二进制为 01100010 字母i的ASCII码为105,转换成二进制为 01 ...

  8. GPU driven pipeline in metal

    https://developer.apple.com/documentation/metal/dynamic_terrain_with_argument_buffers?language=objc ...

  9. 《SVG精髓》笔记(一)

    本文是基于<SVG精髓>一书的简单总结,文中的demo均为该书提供,目的是方便大家使用时快速查阅. 1. 坐标系统 视口(viewport):文档使用的画布区域,表示SVG可见区域的大小, ...

  10. Spring事务管理----------整合学习版

    作者:学无先后 达者为先 Spring提供了一流的事务管理.在Spring中可以支持声明式事务和编程式事务. 一  spring简介 1 Spring的事务       事务管理在应用程序中起着至关重 ...