AtomicIntegerArray

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

可以用原子方式更新其元素的 int 数组

如何使用 AtomicIntegerArray?

1)多线程环境下需要对整形数组中的单个值执行原子更新时使用 AtomicIntegerArray。

使用 AtomicIntegerArray 有什么风险?

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

AtomicIntegerArray 核心操作的实现原理?

创建实例

    private static final VarHandle AA
= MethodHandles.arrayElementVarHandle(int[].class); /**
* 存储 int 值的数组
*/
private final int[] array; /**
* 创建给定长度的新 AtomicIntegerArray 实例,所有元素的值都为 0。
*/
public AtomicIntegerArray(int length) {
array = new int[length];
}

读取指定索引处的值

    /**
* 读取指定索引处的值
* with memory effects as specified by {@link VarHandle#getVolatile}.
*/
public final int get(int i) {
return (int)AtomicIntegerArray.AA.getVolatile(array, i);
}

以原子方式将索引 i 处的元素值加 1,并返回旧值

    /**
* 以原子方式将索引 i 处的元素值加 1,并返回旧值
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*/
public final int getAndIncrement(int i) {
return (int)AtomicIntegerArray.AA.getAndAdd(array, i, 1);
}

以原子方式将索引 i 处的元素值减 1,并返回旧值

    /**
* 以原子方式将索引 i 处的元素值减 1,并返回旧值
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*/
public final int getAndDecrement(int i) {
return (int)AtomicIntegerArray.AA.getAndAdd(array, i, -1);
}

以原子方式将索引 i 处的元素值加 delta,并返回旧值

    /**
* 以原子方式将索引 i 处的元素值加 delta,并返回旧值
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*/
public final int getAndAdd(int i, int delta) {
return (int)AtomicIntegerArray.AA.getAndAdd(array, i, delta);
}

以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值】计算后的新值,并返回旧值

    /**
* 以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值】计算后的新值,并返回旧值
*/
public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
int prev = get(i), next = 0;
for (boolean haveNext = false;;) {
if (!haveNext) {
next = updateFunction.applyAsInt(prev);
}
if (weakCompareAndSetVolatile(i, prev, next)) {
return prev;
}
haveNext = prev == (prev = get(i));
}
}

以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值和参考值】计算后的新值,并返回旧值

    /**
* 以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值和参考值】计算后的新值,并返回旧值
*/
public final int getAndAccumulate(int i, int x,
IntBinaryOperator accumulatorFunction) {
int prev = get(i), next = 0;
for (boolean haveNext = false;;) {
if (!haveNext) {
next = accumulatorFunction.applyAsInt(prev, x);
}
if (weakCompareAndSetVolatile(i, prev, next)) {
return prev;
}
haveNext = prev == (prev = get(i));
}
}

以原子方式将索引 i 处的元素值加 1,并返回新值

    /**
* 以原子方式将索引 i 处的元素值加 1,并返回新值
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*/
public final int incrementAndGet(int i) {
return (int)AtomicIntegerArray.AA.getAndAdd(array, i, 1) + 1;
}

以原子方式将索引 i 处的元素值减 1,并返回新值

    /**
* 以原子方式将索引 i 处的元素值减 1,并返回新值
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*/
public final int decrementAndGet(int i) {
return (int)AtomicIntegerArray.AA.getAndAdd(array, i, -1) - 1;
}

以原子方式将索引 i 处的元素值加 delta,并返回新值

    /**
* 以原子方式将索引 i 处的元素值加 delta,并返回新值
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*/
public final int addAndGet(int i, int delta) {
return (int)AtomicIntegerArray.AA.getAndAdd(array, i, delta) + delta;
}

以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值】计算后的新值,并返回新值

    /**
* 以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值】计算后的新值,并返回新值。
*/
public final int updateAndGet(int i, IntUnaryOperator updateFunction) {
int prev = get(i), next = 0;
for (boolean haveNext = false;;) {
if (!haveNext) {
next = updateFunction.applyAsInt(prev);
}
if (weakCompareAndSetVolatile(i, prev, next)) {
return next;
}
haveNext = prev == (prev = get(i));
}
}

以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值和参考值】计算后的新值,并返回新值

    /**
* 以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值和参考值】计算后的新值,并返回新值
*/
public final int accumulateAndGet(int i, int x,
IntBinaryOperator accumulatorFunction) {
int prev = get(i), next = 0;
for (boolean haveNext = false;;) {
if (!haveNext) {
next = accumulatorFunction.applyAsInt(prev, x);
}
if (weakCompareAndSetVolatile(i, prev, next)) {
return next;
}
haveNext = prev == (prev = get(i));
}
}

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

  1. Java并发包源码分析

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

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

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

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

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

  4. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  5. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

  6. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

  7. zookeeper源码分析之四服务端(单机)处理请求流程

    上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...

  8. zookeeper源码分析之三客户端发送请求流程

    znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...

  9. java使用websocket,并且获取HttpSession,源码分析

    转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的sprin ...

随机推荐

  1. Node+Express+MySql实现简单增删改查和登录

    var express = require('express'); var mysql = require('mysql'); var app = express(); var bodyParser ...

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

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

  3. js日期格式验证

    js日期格式验证 <input type="text" maxLength='10' onkeyup='checkDate(this.value,jQuery(this)); ...

  4. struts2_对Map进行双层迭代

    转自:struts2_对Map进行双层迭代 //后台数据 public String execute() throws Exception { Map<String, List<Produ ...

  5. 说说 HeapSort 堆排序思想,以及个人优化方案。(老物)

    听说你要排上亿个数据之 HeapSort ? 前言 : 来来来,今天我们来说说一个用来排大量数据所用的基础比较排序吧~ 注:阅读本文学习新技能的前置要求为:了解什么是二叉树及其数组性质,如果未达到要求 ...

  6. Linux下RabbitMQ安装、运行与管理

    Linux下RabbitMQ安装.运行与管理 安装erlang 安装参考官网 RabbitMQ的安装需要Erlang的基础环境,必须按照RabbitMQ Erlang版本要求进行安装. 关于Erlan ...

  7. 05-转置-置换-向量空间R

    一.置换矩阵 一个矩阵的行或者列交换,可以借助另外一个矩阵相乘来实现 首先是行交换: $\underbrace{\left[\begin{array}{ccc}{1} & {1} & ...

  8. 一、ASP.NET Iframework_SignalR永久连接类(v2)

    一.新建项目,选MVC项目默认 添加mvc文件夹和核心引用 二.添加SignaIR包 SignalR的准备:NuGet包管理器搜索:工具——>库程序包管理器——>Microsoft.Asp ...

  9. 利用描述符自定义property

    class Lazyproperty: def __init__(self,func): #传的func函数是被描述的类中的函数属性 self.func = func def __get__(self ...

  10. VB学习一

    一.基础函数 CStr() 函数转化表达式为一个字符串 Trim() 移除字符串两侧的空白字符串或者其他预定义字符 成功:返回删除后的字符串 失败:返回空字符串 VBA.Mid(string,star ...