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. Sublime Text 3 安装及汉化操作

    Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等.还可自定义键绑定,菜单和工具栏.Sublime Text 的主要功能包括:拼写检查,书签,完整的 ...

  2. 检验Excel中数据是否与数据库中数据重复

    #region 记录Excel中的重复列 /// <summary> /// 记录Excel中的重复列 /// </summary> /// <param name=&q ...

  3. 使用idea实现SSM框架整合

    SM框架整合 1      使用idea创建一个maven webapp项目 到此为止项目初步建立,需要等待maven对项目结构进行组织,直到状态栏的进度条完成,且项目的目录结构如下: 2      ...

  4. loadkeys - 调入键盘翻译表

    总览 (SYNOPSIS) loadkeys [ -d --default ] [ -h --help ] [ -q --quiet ] [ -v --verbose [ -v --verbose ] ...

  5. 03python面向对象编程之多态和枚举6

    7.多态性 对于弱类型的语言来说,变量并没有声明类型,因此同一个变量完全可以在不同的时间引用不同的对象.当同一个变量在调用同一个方法时,完全可能呈现出多种行为(具体呈现出哪种行为由该变量所引用的对象来 ...

  6. 如何在vue中引入图片?

    当我们在Vue.js项目中引用图片时,关于图片路径有以下几种情形: 使用一. 我们在data里面定义好图片路径 imgUrl:'../assets/logo.png' 然后,在template模板里面 ...

  7. 【前端】HTML基础

    前端 HTML:一个人 CSS:这个人的衣服 JS:这个人的行为 1 head标签 head相关标签 <!--html5--> <!DOCTYPE html> <html ...

  8. Warning: Failed prop type: Invalid prop `value` supplied to `Picker`.报错问题

    在使用antd的日期插件时,不留意就会报各种错误. 例如:Warning: Failed prop type: Invalid prop `value` supplied to `Picker`. 这 ...

  9. Java——static

    [static] <1>static成员变量存储在内存data segment区域,不是存放在堆中. <2>静态成员变量属于整个类,任何一个对象都可以访问这个值:如果没有对象, ...

  10. ipcloud上传裁切图片

    主页: <!doctype html> <html> <head> <meta charset="utf-8"> <meta ...