AtomicStampedReference

AtomicStampedReference 能解决什么问题?什么时候使用 AtomicStampedReference?

1)AtomicStampedReference 维护带有整数标识的对象引用,可以用原子方式对其进行更新。
2)AtomicStampedReference 能够解决 CAS 的 ABA 问题。

如何使用 AtomicStampedReference?

1)使用 AtomicStampedReference 解决无锁 CAS 过程中的 ABA 问题,特别是涉及资金时。

使用 AtomicStampedReference 有什么风险?

1)高并发场景下,自旋 CAS 长时间失败会导致 CPU 飙升

AtomicStampedReference 核心操作的实现原理?

创建实例

    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<>(reference, stamp);
}
} private volatile Pair<V> pair; /**
* 创建具有给定对象引用和标识值的新 AtomicStampedReference 实例
*/
public AtomicStampedReference(V initialRef, int initialStamp) {
pair = Pair.of(initialRef, initialStamp);
}

尝试原子更新

    /**
* 如果旧引用==expectedReference && 旧整形标记==expectedStamp,
* 则尝试原子更新引用为 newReference,时间标记为 newStamp
*/
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
final Pair<V> current = pair;
return
expectedReference == current.reference &&
expectedStamp == current.stamp &&
(newReference == current.reference &&
newStamp == current.stamp ||
casPair(current, Pair.of(newReference, newStamp)));
}

读取值

    /**
* 读取引用值
*/
public V getReference() {
return pair.reference;
} /**
* 读取整形标记
*/
public int getStamp() {
return pair.stamp;
} /**
* 读取引用值,并将整形标记存储到形参数组索引为 0 的位置
*/
public V get(int[] stampHolder) {
final Pair<V> pair = this.pair;
stampHolder[0] = pair.stamp;
return pair.reference;
}

写入值

    /**
* 无条件地更新引用值和时间标记
*/
public void set(V newReference, int newStamp) {
final Pair<V> current = pair;
if (newReference != current.reference || newStamp != current.stamp) {
this.pair = Pair.of(newReference, newStamp);
}
}

原子更新值,并发更新时可能失败

    /**
* 如果旧引用==expectedReference && 旧整形标记==expectedStamp,
* 则尝试原子更新引用为 newReference,时间标记为 newStamp
*/
public boolean weakCompareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
return compareAndSet(expectedReference, newReference,
expectedStamp, newStamp);
} /**
* 如果旧引用==expectedReference && 旧整形标记==expectedStamp,
* 则尝试原子更新引用为 newReference,时间标记为 newStamp
*/
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
final Pair<V> current = pair;
return
expectedReference == current.reference &&
expectedStamp == current.stamp &&
(newReference == current.reference &&
newStamp == current.stamp ||
casPair(current, Pair.of(newReference, newStamp)));
} private static final VarHandle PAIR;
static {
try {
final MethodHandles.Lookup l = MethodHandles.lookup();
PAIR = l.findVarHandle(AtomicStampedReference.class, "pair",
Pair.class);
} catch (final ReflectiveOperationException e) {
throw new Error(e);
}
} private boolean casPair(Pair<V> cmp, Pair<V> val) {
return AtomicStampedReference.PAIR.compareAndSet(this, cmp, val);
}

AtomicStampedReference 源码分析的更多相关文章

  1. 死磕 java并发包之AtomicStampedReference源码分析(ABA问题详解)

    问题 (1)什么是ABA? (2)ABA的危害? (3)ABA的解决方法? (4)AtomicStampedReference是什么? (5)AtomicStampedReference是怎么解决AB ...

  2. AtomicStampedReference源码分析

    public class Snippet { //修改的是AtomicStampedReference对象里面的值了. public static void main(String[] args) { ...

  3. AtomicInteger源码分析——基于CAS的乐观锁实现

    AtomicInteger源码分析——基于CAS的乐观锁实现 1. 悲观锁与乐观锁 我们都知道,cpu是时分复用的,也就是把cpu的时间片,分配给不同的thread/process轮流执行,时间片与时 ...

  4. Java高并发之无锁与Atomic源码分析

    目录 CAS原理 AtomicInteger Unsafe AtomicReference AtomicStampedReference AtomicIntegerArray AtomicIntege ...

  5. 并发-AtomicInteger源码分析—基于CAS的乐观锁实现

    AtomicInteger源码分析—基于CAS的乐观锁实现 参考: http://www.importnew.com/22078.html https://www.cnblogs.com/mantu/ ...

  6. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  7. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  8. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

  9. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

随机推荐

  1. RabbitMq学习1-介绍、安装和配置

    一.简介 1.MQ框架非常之多,比较流行的有RabbitMq.ActiveMq.ZeroMq.kafka,以及阿里开源的RocketMQ       2.AMQP是消息队列的一个协议. 3.Rabbi ...

  2. asp,net 传值方式 优缺点比较

    .net C#中页面之间传值传参的六种方法 1.QueryString是一种非常简单的传值方式,他可以将传送的值显示在浏览器的地址栏中.如果是传递一个或多个安全性要求不高或是结构简单的数值时,可以使用 ...

  3. flask之上下文管理

    简单来说,falsk上下文管理可以分为三个阶段: 1.请求进来时,将请求鞋底的相关数据放入上下文管理中进行管理 2.在视图函数中,要去上下文管理中取值 3.请求响应之后,要将上下文管理中的数据清除 详 ...

  4. 005-sort 命令使用

    字符处理命令 sort 排序命令 排序选项: -f, --ignore-case 忽略字母大小写 -n, --numeric-sort 根据字符串数值比较 -r, --reverse 逆序输出排序结果 ...

  5. 07java进阶——集合框架(set)

    1.list接口中常用的特有方法 package cn.jxufe.java.chapter7; import java.util.ArrayList; import java.util.List; ...

  6. 网络流 最大流SAPkuangbin模板

    hdu 1532 求1~n的最大流 #include<stdio.h> #include<string.h> #include<algorithm> #includ ...

  7. webpack Entrypoint undefined = index.html

    报错: module.exports增加配置stats: { children: false }即可解决:

  8. python 小游戏,和电脑玩剪刀石头布

    # -*- coding: utf-8 -*- """ Created on Fri Oct 25 16:28:12 2019 if判断综合演练,剪刀石头布 @autho ...

  9. 【03】Python 文件读写 JSON

    1 打开文件 文件操作步骤: 1.打开文件获取文件的句柄,句柄就理解为这个文件 2.通过文件句柄操作文件 3.关闭文件. 1.1 打开方法 f = open('xxx.txt') #需f.close( ...

  10. linux文件系统的类型

    文件系统的类型 兄弟连介绍-Linux有四种基本文件系统类型:普通文件.目录文件.连接文件和特殊文件,可用file命令来识别. 普通文件:如文本文件.C语言元代码.SHELL脚本.二进制的可执行文件等 ...