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 ...
随机推荐
- 小白学Python——Matplotlib 学习(1)
众所周知,通过数据绘图,我们可以将枯燥的数字转换成容易被人们接受的图表,从而让人留下更加深刻的印象.而大多数编程语言都有自己的绘图工具,matplotlib就是基于Python的绘图工具包,使用它我们 ...
- 简述COOKIE和SESSION的区别与联系?
cookie 和session 的区别:1.cookie数据存放在客户的浏览器上,session数据放在服务器上.2.cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗 ...
- SCUT - 161 - 灯游 - 数学
https://scut.online/p/161 很显然一个数被开关的概率是他的因子的个数的占比. 然后又很显然其实这个总的概率就是一个二项式求和. 模拟这个过程WA了8发.正常,毕竟浮点误差累积比 ...
- 计算机系统结构总结_Instruction Set Architecture
Textbook:<计算机组成与设计——硬件/软件接口> HI<计算机体系结构——量化研究方法> QR 这节我们来看CPU内部的一些东西. Instruct ...
- vue编写轮播图组件
<template> <div id="slider"> <div class="window" @mouseover=& ...
- Redis持久化rdb&aof
Redis持久化rdb&aof 前言 持久化:即把数据存储于断电后不会丢失的设备中,通常是硬盘 常见的持久化方式: 主从:通过从服务器保持持久化,如mongoDB的replication se ...
- 通过runtime对类别进行属性的扩展
category使用 objc_setAssociatedObject/objc_getAssociatedObject 实现添加属性 属性 其实就是 get/set 方法. 我们可以使用 objc ...
- 算法学习之选择排序算法的python实现
——参考自<算法图解> def findSmallest(arr): # 假设第一个元素最小 smallest = arr[0] smallest_index = 0 for i in r ...
- P3833 [SHOI2012]魔法树 (树链剖分模板题)
题目链接:https://www.luogu.org/problem/P3833 题目大意:有一颗含有n个节点的树,初始时每个节点的值为0,有以下两种操作: 1.Add u v d表示将点u和v之间的 ...
- IAR
IAR是什么 支持众多半导体公司产品的c处理器 http://www.rimelink.com/pr.jsp