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 源码分析的更多相关文章

  1. Java并发包源码分析

    并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可交互性将大大改善.现代的PC都有多个CPU或一个CPU中有多个 ...

  2. rxjava源码分析

    RXjava响应式编程 此文作者大暴雨原创,转载请注明出处. 如果线程的知识不是很丰富,请先查看     rxjava源码中的线程知识  一文 rxjava总结就是:异步实现主要是通过扩展观察者模式 ...

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

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

  4. zuul源码分析-探究原生zuul的工作原理

    前提 最近在项目中使用了SpringCloud,基于zuul搭建了一个提供加解密.鉴权等功能的网关服务.鉴于之前没怎么使用过Zuul,于是顺便仔细阅读了它的源码.实际上,zuul原来提供的功能是很单一 ...

  5. RxJava2 中多种取消订阅 dispose 的方法梳理( 源码分析 )

    Github 相关代码: Github地址 一直感觉 RxJava2 的取消订阅有点混乱, 这样也能取消, 那样也能取消, 没能系统起来的感觉就像掉进了盘丝洞, 迷乱… 下面说说这几种情况 几种取消的 ...

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

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

  7. SparkRPC源码分析之RPC管道与消息类型

    SparkRPC源码分析之RPC管道与消息类型我们前面看过了netty基础知识扫盲,那我们应该明白,ChannelHandler这个组件内为channel的各种事件提供了处理逻辑,也就是主要业务逻辑写 ...

  8. 源码分析 RocketMQ DLedger(多副本) 之日志复制(传播)

    目录 1.DLedgerEntryPusher 1.1 核心类图 1.2 构造方法 1.3 startup 2.EntryDispatcher 详解 2.1 核心类图 2.2 Push 请求类型 2. ...

  9. RxJava 2.x 源码分析

    本次分析的 RxJava 版本信息如下: 12 implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'implementation 'io.reac ...

随机推荐

  1. 画一个心送给心爱的小姐姐,Python绘图库Turtle

    Python绘图库Turtle Turtle介绍 Turtle是Python内嵌的绘制线.圆以及其他形状(包括文本)的图形模块. 一个Turtle实际上是一个对象,在导入Turtle模块时,就创建了对 ...

  2. selenium 教程

    selenium 本身是一套web自动化测试工具,但其经常被用于爬虫,解决一些复杂爬虫的问题. selenium 用于爬虫时,相当于模拟人操作浏览器. 浏览器驱动 使用 selenium 需要先安装 ...

  3. 深入理解 JavaScript中的变量、值、传参

    1. demo 如果你对下面的代码没有任何疑问就能自信的回答出输出的内容,那么本篇文章就不值得你浪费时间了. var var1 = 1 var var2 = true var var3 = [1,2, ...

  4. 又一Tab切换效果(js实现)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. C++ delete仍可访问的问题

    C++ delete和置为NULL 先上一段代码: class Object { public: explicit Object(int num) : m_num(num){} void functi ...

  6. 14-jquery元素节点操作

    **创建节点** ```var Div = $('<div>');var Div2 = $('<div>这是一个div元素</div>');``` **插入节点** ...

  7. vue filters过滤

    <template> <div class="filters"> <h1 v-text="filtersTitle">< ...

  8. 基于Red5与ffmpeg实现rtmp处理NVR或摄像头的监控视频处理方案

    背景 各大监控视频平台厂商与外对接均是基于IE的OCX插件方式提供实时视频查看.历史视频回放与历史视频下载.在h5已大行其道的当下,基于IE的OCX插件方式已满足不了广大客户的实际需求,因此需要一个兼 ...

  9. 中国各个省市县的人口统计,echart展示

    公司要做一个excel形式的人口统计表,我感觉应该更直观一些展示,所以就选用了echart进行展示,由于时间短所以制作的比较简单粗糙,但相应的数据还是有很大的可参考性. 刚好下载了jfinal3.5, ...

  10. 微信小程序(19)-- 从底部向上滑出的动画效果

    从底部向上滑出的动画效果: 用到了小程序的触摸事件bindtouchmove,以及创建一个annimation对象,完成动画操作之后使用animation这个对象的export()方法导出动画数据. ...