AtomicReference 源码分析
AtomicReference
AtomicReference 能解决什么问题?什么时候使用 AtomicReference?
1)AtomicReference 可以原子更新引用对象。
2)compareAndSet 操作是一条 CPU 指令,不会发生上下文切换,执行效率高。
使用锁保证对象同步时,会触发一次系统调用和上下文切换,执行效率低。
如何使用 AtomicReference?
1)多线程环境下需要并发修改对象的多个属性时,使用 AtomicReference【
读取、修改、更新需要在同一个循环中,并根据 compareAndSet 的结果来判断是否要继续自旋】。
使用 AtomicReference 有什么风险?
1)高并发场景下,自旋 CAS 长时间失败会导致 CPU 飙升
AtomicReference 核心操作的实现原理?
创建实例
private static final VarHandle VALUE;
static {
try {
final MethodHandles.Lookup l = MethodHandles.lookup();
VALUE = l.findVarHandle(AtomicReference.class, "value", Object.class);
} catch (final ReflectiveOperationException e) {
throw new Error(e);
}
}
/**
* volatile 引用值
*/
private volatile V value;
/**
* 基于初始对象 initialValue 创建一个 AtomicReference 实例
*/
public AtomicReference(V initialValue) {
value = initialValue;
}
/**
* 创建一个关联对象为 null 的 AtomicReference 实例
*/
public AtomicReference() {
}
尝试原子更新
/**
* 原子的将引用值设置为 newValue,如果旧值 == expectedValue,设置成功返回 true,否则返回 false。
*
* @param expectedValue 期望值
* @param newValue 新值
*/
public final boolean compareAndSet(V expectedValue, V newValue) {
return AtomicReference.VALUE.compareAndSet(this, expectedValue, newValue);
}
读取当前值
/**
* 读取当前值
* with memory effects as specified by {@link VarHandle#getVolatile}.
*/
public final V get() {
return value;
}
原子地将旧值更新为 newValue,并返回旧值
/**
* 原子地将旧值更新为 newValue,并返回旧值
* with memory effects as specified by {@link VarHandle#getAndSet}.
*/
@SuppressWarnings("unchecked")
public final V getAndSet(V newValue) {
return (V)AtomicReference.VALUE.getAndSet(this, newValue);
}
使用函数式接口 updateFunction 基于旧值计算新值,并将旧值替换为计算值,返回旧值
/**
* 使用函数式接口 updateFunction 基于旧值计算新值,并将旧值替换为计算值,返回旧值
*/
public final V getAndUpdate(UnaryOperator<V> updateFunction) {
V prev = get(), next = null;
for (boolean haveNext = false;;) {
if (!haveNext) {
next = updateFunction.apply(prev);
}
if (weakCompareAndSetVolatile(prev, next)) {
return prev;
}
haveNext = prev == (prev = get());
}
}
/**
* 如果当前值==expectedValue,则尝试原子地将其更新为 newValue,更新成功返回 true
* with memory effects as specified by
* {@link VarHandle#weakCompareAndSet}.
*/
public final boolean weakCompareAndSetVolatile(V expectedValue, V newValue) {
return AtomicReference.VALUE.weakCompareAndSet(this, expectedValue, newValue);
}
使用函数式接口 updateFunction 基于旧值计算新值,并将旧值替换为计算值,返回新值
/**
* 使用函数式接口 updateFunction 基于旧值计算新值,并将旧值替换为计算值,返回新值
*/
public final V updateAndGet(UnaryOperator<V> updateFunction) {
V prev = get(), next = null;
for (boolean haveNext = false;;) {
if (!haveNext) {
next = updateFunction.apply(prev);
}
if (weakCompareAndSetVolatile(prev, next)) {
return next;
}
haveNext = prev == (prev = get());
}
}
使用函数式接口 accumulatorFunction 基于旧值和形参 x 计算新值,并将旧值替换为计算值,返回旧值
/**
* 使用函数式接口 accumulatorFunction 基于旧值和形参 x 计算新值,并将旧值替换为计算值,返回旧值
*/
public final V getAndAccumulate(V x,
BinaryOperator<V> accumulatorFunction) {
V prev = get(), next = null;
for (boolean haveNext = false;;) {
if (!haveNext) {
next = accumulatorFunction.apply(prev, x);
}
if (weakCompareAndSetVolatile(prev, next)) {
return prev;
}
haveNext = prev == (prev = get());
}
}
使用函数式接口 accumulatorFunction 基于旧值和形参 x 计算新值,并将旧值替换为计算值,返回新值
/**
* 使用函数式接口 accumulatorFunction 基于旧值和形参 x 计算新值,并将旧值替换为计算值,返回新值
*/
public final V accumulateAndGet(V x,
BinaryOperator<V> accumulatorFunction) {
V prev = get(), next = null;
for (boolean haveNext = false;;) {
if (!haveNext) {
next = accumulatorFunction.apply(prev, x);
}
if (weakCompareAndSetVolatile(prev, next)) {
return next;
}
haveNext = prev == (prev = get());
}
}
AtomicReference 源码分析的更多相关文章
- Java并发包源码分析
并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可交互性将大大改善.现代的PC都有多个CPU或一个CPU中有多个 ...
- rxjava源码分析
RXjava响应式编程 此文作者大暴雨原创,转载请注明出处. 如果线程的知识不是很丰富,请先查看 rxjava源码中的线程知识 一文 rxjava总结就是:异步实现主要是通过扩展观察者模式 ...
- Java高并发之无锁与Atomic源码分析
目录 CAS原理 AtomicInteger Unsafe AtomicReference AtomicStampedReference AtomicIntegerArray AtomicIntege ...
- zuul源码分析-探究原生zuul的工作原理
前提 最近在项目中使用了SpringCloud,基于zuul搭建了一个提供加解密.鉴权等功能的网关服务.鉴于之前没怎么使用过Zuul,于是顺便仔细阅读了它的源码.实际上,zuul原来提供的功能是很单一 ...
- RxJava2 中多种取消订阅 dispose 的方法梳理( 源码分析 )
Github 相关代码: Github地址 一直感觉 RxJava2 的取消订阅有点混乱, 这样也能取消, 那样也能取消, 没能系统起来的感觉就像掉进了盘丝洞, 迷乱… 下面说说这几种情况 几种取消的 ...
- 死磕 java并发包之AtomicStampedReference源码分析(ABA问题详解)
问题 (1)什么是ABA? (2)ABA的危害? (3)ABA的解决方法? (4)AtomicStampedReference是什么? (5)AtomicStampedReference是怎么解决AB ...
- SparkRPC源码分析之RPC管道与消息类型
SparkRPC源码分析之RPC管道与消息类型我们前面看过了netty基础知识扫盲,那我们应该明白,ChannelHandler这个组件内为channel的各种事件提供了处理逻辑,也就是主要业务逻辑写 ...
- 源码分析 RocketMQ DLedger(多副本) 之日志复制(传播)
目录 1.DLedgerEntryPusher 1.1 核心类图 1.2 构造方法 1.3 startup 2.EntryDispatcher 详解 2.1 核心类图 2.2 Push 请求类型 2. ...
- RxJava 2.x 源码分析
本次分析的 RxJava 版本信息如下: 12 implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'implementation 'io.reac ...
随机推荐
- 2、Java调用C语言(JNative法)
这个方法也是挺麻烦的…… 一.下载JNative.jar,把它放在你jdk下的\jre\lib\ext目录下 二.在 F:\MinGW\JNative 新建 Test.java: public cla ...
- 03-Django-models
# Models 模型 - ORM - ObjectRelationMap : 把面向对象思想转换成关系数据库思想.操作上把类等价于表格 - 类对应表格 - 类中的属性对应表中的字段 - 在应用中的m ...
- 34. Find First and Last Position of Element in Sorted Array (JAVA)
Given an array of integers nums sorted in ascending order, find the starting and ending position of ...
- iOS 审核app被拒绝的各种理由以及翻译
原 apps被拒绝的各种理由以及翻译:http://my.oschina.net/201003674/blog/356189#OSC_h1_3 1. Terms and conditions(法律与条 ...
- SQL SERVER 索引维护
-- 全数据库索引重建 DECLARE @name varchar(100)DECLARE authors_cursor CURSOR FOR Select [name] from sysobject ...
- 【转】uboot中的mmc命令
转自:https://www.cnblogs.com/yxwkf/p/3855383.html 1:mmcinfo 输入: mmcinfo 显示结果:Manufacturer ID: 45OEM: 1 ...
- 007-cobbler+koan自动化重装系统
一.操作步骤 1.在使用cobbler自动化安装的虚拟机上做以下操作 2.安装epel源(先配置好yum) [root@localhost ~]# yum install epel-release - ...
- 牛客假日团队赛2 C 修围栏 ( 哈夫曼树,贪心)
链接:https://ac.nowcoder.com/acm/contest/924/C 来源:牛客网 修围栏 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言6 ...
- 10年前文章_使用opkg 管理软件更新
为避免调试过程中每次都要刷写flash, 可以使用opkg 管理工具来实现单个包更新 一.首先配置http 服务器,使之能访问生成的ipkg 格式的包,例如你的工作目录在/home/xxx/build ...
- Python核心技术与实战——十|面向对象的案例分析
今天通过面向对象来对照一个案例分析一下,主要模拟敏捷开发过程中的迭代开发流程,巩固面向对象的程序设计思想. 我们从一个最简单的搜索做起,一步步的对其进行优化,首先我们要知道一个搜索引擎的构造:搜索器. ...