AtomicStampedReference 源码分析
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 源码分析的更多相关文章
- 死磕 java并发包之AtomicStampedReference源码分析(ABA问题详解)
问题 (1)什么是ABA? (2)ABA的危害? (3)ABA的解决方法? (4)AtomicStampedReference是什么? (5)AtomicStampedReference是怎么解决AB ...
- AtomicStampedReference源码分析
public class Snippet { //修改的是AtomicStampedReference对象里面的值了. public static void main(String[] args) { ...
- AtomicInteger源码分析——基于CAS的乐观锁实现
AtomicInteger源码分析——基于CAS的乐观锁实现 1. 悲观锁与乐观锁 我们都知道,cpu是时分复用的,也就是把cpu的时间片,分配给不同的thread/process轮流执行,时间片与时 ...
- Java高并发之无锁与Atomic源码分析
目录 CAS原理 AtomicInteger Unsafe AtomicReference AtomicStampedReference AtomicIntegerArray AtomicIntege ...
- 并发-AtomicInteger源码分析—基于CAS的乐观锁实现
AtomicInteger源码分析—基于CAS的乐观锁实现 参考: http://www.importnew.com/22078.html https://www.cnblogs.com/mantu/ ...
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
- HashMap与TreeMap源码分析
1. 引言 在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...
- nginx源码分析之网络初始化
nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...
- zookeeper源码分析之五服务端(集群leader)处理请求流程
leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...
随机推荐
- 03: django进阶篇
1.1 cookie 1.cookie简介 1. cookie实质就是客户端硬盘中存放的键值对,利用这个特性可以用来做用户验证 2. 比如:{“username”: “dachengzi”} #再次访 ...
- SCUT - 485 - 质因数计数 - 原根
https://scut.online/p/485 给定a和n,求有多少个质数p,满足n是使得a^n=1 mod p成立的最小正整数. 翻译:求有多少个质数p,使得a模p的阶delta_m(a)是n ...
- python学习第五十二天logging模块的使用
很多程序都有记录日志的需求,并且日志包含的信息即有正常的程序访问日志,还可能有错误,警告等信息输出,python的 logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,loggin ...
- js的抖动及防抖和节流
js的抖动 在 js 中 改变窗口大小 & 上下滚动滚动条 & 反复向输入框中输入内容 ... , 如果绑定了相应的事件 , 这些事件的触发频率非常高, 严重影响用户体验和服务器的性 ...
- pycharm链接数据库以及连接时候出现错误的集合
1.pycharm如何直接连接数据库? 作用:这是一种管理数据库的方式而已,因为在开发过程中结合使用还是不错的!当然,还有有很多管理数据库的工具和方法. 比如:navicat工具 1.1 如何找到管 ...
- PowerEdge T630服务器安装机器学习环境(Ubuntu18.04、Nvidia 1080Ti驱动、CUDA及CUDNN安装)
安装步骤 在开始安装之前,我要说明一下,这个Ubuntu18.04系统的安装,使用的连接线(就是服务器和电脑显示器的连接线)必须两头都是VGA连接线,不能使用VGA转HDMI连接线,也不能用DVI转D ...
- python-xss攻击和单例模式
1.python中单例模式 class Foo: instance = None def __new__(cls, *args, **kwargs): if not Foo.instance: Foo ...
- Apache 网站日志分析
1.获得访问前 10 位的 ip 地址 [root@apache ~]# cat access_log |awk '{print $1}'|sort|uniq -c|sort -nr|head -10 ...
- TCP软件环境测试
利用合宙官网上的云平台->TCP透传云,建立一个TCP服务. http://tcplab.openluat.com/ [注意事项] 如3分钟内没有客户端接入则会自动关闭. 每个服务器最大客户端连 ...
- python socket--TCP解决粘包的方法
1.为什么会出现粘包?? 让我们基于tcp先制作一个远程执行命令的程序(1:执行错误命令 2:执行ls 3:执行ifconfig) 注意注意注意: res=subprocess.Popen(cmd.d ...