AtomicIntegerFieldUpdater

AtomicIntegerFieldUpdater 能解决什么问题?什么时候使用 AtomicIntegerFieldUpdater?

1)字段必须是 volatile 类型的实例变量。
2)调用者能够直接通过反射的方式操作对象字段,而不存在可见性问题。

如何使用 AtomicIntegerFieldUpdater?

1)指定对象的 int 值需要支持并发多读少写的场景下,使用 AtomicIntegerFieldUpdater。

使用 AtomicIntegerFieldUpdater 有什么风险?

1)高并发场景下,自旋 CAS 长时间失败会导致 CPU 飙升。

AtomicIntegerFieldUpdater 核心操作的实现原理?

创建实例

    /**
* 基于指定的 Class 类型和字段名称创建一个 AtomicIntegerFieldUpdater 实例,
* 字段类型必须是 volatile int。
*/
@CallerSensitive
public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
String fieldName) {
return new AtomicIntegerFieldUpdaterImpl<U>
(tclass, fieldName, Reflection.getCallerClass());
}

尝试以原子的方式更新目标对象的 int 值

AtomicIntegerFieldUpdaterImpl#
@Override
public boolean compareAndSet(T obj, int expect, int update) {
accessCheck(obj);
return AtomicIntegerFieldUpdaterImpl.U.compareAndSetInt(obj, offset, expect, update);
}

获取此更新器管理的,在给定对象的字段中保持的当前值

AtomicIntegerFieldUpdaterImpl#
@Override
public int get(T obj) {
accessCheck(obj);
return AtomicIntegerFieldUpdaterImpl.U.getIntVolatile(obj, offset);
}

以原子方式将此更新器管理的给定对象的当前值 + 1,并返回旧值

AtomicIntegerFieldUpdaterImpl#
public final int getAndIncrement(T obj) {
return getAndAdd(obj, 1);
} public final int getAndAdd(T obj, int delta) {
accessCheck(obj);
return U.getAndAddInt(obj, offset, delta);
} /**
* 检查目标对象是否是指定 Class 类型的实例
*/
private void accessCheck(T obj) {
if (!cclass.isInstance(obj)) {
throwAccessCheckException(obj);
}
}

以原子方式将此更新器管理的给定对象的当前值 - 1,并返回旧值

AtomicIntegerFieldUpdaterImpl#
@Override
public int getAndDecrement(T obj) {
return getAndAdd(obj, -1);
}

以原子方式将此更新器管理的给定对象的当前值 + delta,并返回旧值

AtomicIntegerFieldUpdaterImpl#
@Override
public int getAndAdd(T obj, int delta) {
accessCheck(obj);
return AtomicIntegerFieldUpdaterImpl.U.getAndAddInt(obj, offset, delta);
}

以原子方式将此更新器管理的给定对象的当前值更新为一元函数式接口的计算值,并返回旧值

    /**
* 以原子方式将此更新器管理的给定对象的当前值更新为一元函数式接口的计算值,并返回旧值
*/
public final int getAndUpdate(T obj, IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get(obj);
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(obj, prev, next));
return prev;
}

以原子方式将此更新器管理的给定对象的当前值更新为二元函数式接口的计算值,并返回旧值

    /**
* 以原子方式将此更新器管理的给定对象的当前值更新为二元函数式接口的计算值,并返回旧值
*/
public final int getAndAccumulate(T obj, int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get(obj);
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(obj, prev, next));
return prev;
}

以原子方式将此更新器管理的给定对象的当前值 + 1,并返回新值

AtomicIntegerFieldUpdaterImpl#
@Override
public int incrementAndGet(T obj) {
return getAndAdd(obj, 1) + 1;
} @Override
public int getAndAdd(T obj, int delta) {
accessCheck(obj);
return AtomicIntegerFieldUpdaterImpl.U.getAndAddInt(obj, offset, delta);
} /**
* 检查目标对象是否是指定 Class 类型的实例
*/
private void accessCheck(T obj) {
if (!cclass.isInstance(obj)) {
throwAccessCheckException(obj);
}
}

以原子方式将此更新器管理的给定对象的当前值 - 1,并返回新值

AtomicIntegerFieldUpdaterImpl#
@Override
public int decrementAndGet(T obj) {
return getAndAdd(obj, -1) - 1;
}

以原子方式将此更新器管理的给定对象的当前值 + delta,并返回新值

AtomicIntegerFieldUpdaterImpl#
@Override
public int addAndGet(T obj, int delta) {
return getAndAdd(obj, delta) + delta;
}

以原子方式将此更新器管理的给定对象的当前值更新为一元函数式接口的计算值,并返回新值

    /**
* 以原子方式将此更新器管理的给定对象的当前值更新为一元函数式接口的计算值,并返回新值
*/
public final int updateAndGet(T obj, IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get(obj);
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(obj, prev, next));
return next;
}

以原子方式将此更新器管理的给定对象的当前值更新为二元函数式接口的计算值,并返回新值

    /**
* 以原子方式将此更新器管理的给定对象的当前值更新为二元函数式接口的计算值,并返回新值
*/
public final int accumulateAndGet(T obj, int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get(obj);
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(obj, prev, next));
return next;
}

AtomicIntegerFieldUpdater 源码分析的更多相关文章

  1. rxjava源码分析

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

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

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

  3. Netty中NioEventLoopGroup的创建源码分析

    NioEventLoopGroup的无参构造: public NioEventLoopGroup() { this(0); } 调用了单参的构造: public NioEventLoopGroup(i ...

  4. spark 源码分析之十七 -- Spark磁盘存储剖析

    上篇文章 spark 源码分析之十六 -- Spark内存存储剖析 主要剖析了Spark 的内存存储.本篇文章主要剖析磁盘存储. 总述 磁盘存储相对比较简单,相关的类关系图如下: 我们先从依赖类 Di ...

  5. Netty中的ChannelPipeline源码分析

    ChannelPipeline在Netty中是用来处理请求的责任链,默认实现是DefaultChannelPipeline,其构造方法如下: private final Channel channel ...

  6. netty(六) buffer 源码分析

    问题 : netty的 ByteBuff 和传统的ByteBuff的区别是什么? HeapByteBuf 和 DirectByteBuf 的区别 ? HeapByteBuf : 使用堆内存,缺点 ,s ...

  7. spark源码分析以及优化

    第一章.spark源码分析之RDD四种依赖关系 一.RDD四种依赖关系 RDD四种依赖关系,分别是 ShuffleDependency.PrunDependency.RangeDependency和O ...

  8. Netty源码分析之ByteBuf引用计数

    引用计数是一种常用的内存管理机制,是指将资源的被引用次数保存起来,当被引用次数变为零时就将其释放的过程.Netty在4.x版本开始使用引用计数机制进行部分对象的管理,其实现思路并不是特别复杂,它主要涉 ...

  9. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

随机推荐

  1. 通过编写串口助手工具学习MFC过程——(八)遇到的一些问题

    通过编写串口助手工具学习MFC过程 因为以前也做过几次MFC的编程,每次都是项目完成时,MFC基本操作清楚了,但是过好长时间不再接触MFC的项目,再次做MFC的项目时,又要从头开始熟悉.这次通过做一个 ...

  2. vue : 无法加载文件 C:\Users\XXX\AppData\Roaming\npm\vue.ps1,因为在此系统上禁止运行脚本

    问题: 使用命令行安装完成vue/cli后,使用vue ui无法创建demo vue : 无法加载文件 C:\Users\yangx\AppData\Roaming\npm\vue.ps1,因为在此系 ...

  3. (ES6)数据处理常用工具方法收集(更新状态: on)

    1. 扁平数组转成tree结构(来源: StackOverflow的印度老哥写的) // Data Set // One top level comment var comments = [{ id: ...

  4. Cross-Origin-Resource-Sharing-Solutions

    from:https://github.com/hijiangtao/hijiangtao.github.io/blob/master/_posts/2017-06-13-Cross-Origin-R ...

  5. vue 使用element-ui中的Notification自定义按钮并实现关闭功能以及如何处理多个通知

    使用element-ui中的Notification,只有一个message属性是有很大的操作空间,其余的都是写死的,无法进行扩展,达不到想要的效果.所以只能在message上下功夫. 在elemen ...

  6. Docker拷贝宿主机与容器中的文件

    如果我们需要将宿主机文件拷贝到容器内可以使用 docker cp 命令,也可以将文件从容器内拷贝到宿主机 将宿主机文件拷贝到容器内 docker cp 要拷贝的宿主机文件或目录 容器名称:容器文件或目 ...

  7. 以当前时间作为GUID的方法

    在C#中,系统提供了GUID类,用户可以通过该类来获得128位的唯一标识,但是该标识不具有可读性,很难把该GUID显示在界面上,以当前时间精确到毫秒来作为GUID是一个比较不错的做法,但是DateTi ...

  8. lilo.conf - lilo 配置文件

    描述 默认情况下,本文件 ( /etc/lilo.conf ) 由引导管理程序 lilo 读取 (参考 lilo(8)). 它看起来可能象这样: boot = /dev/hda delay = 40 ...

  9. Linux学习--第七天--用户和用户组

    用户和用户组 usermod -a -G groupname username // 将已有用户添加到已有用户组 /etc/passwd michael:x:500:500:CentOS:/home/ ...

  10. LTM_本地流量管理(一)

    基本元素及概念 Node:节点,即服务器的IP地址. Member:成员,即一个服务,用IP+端口表示. Pool:池:一个或多个Member的逻辑分组,一个Pool表示一个应用,每个Pool都有自己 ...