AtomicInteger

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

支持原子更新的 int 值。

如何使用 AtomicInteger?

1)需要被多线程并发访问的原子计数器。
2)使用 AtomicInteger.compareAndSet 实现非阻塞的线程安全工具类。

使用 AtomicInteger 有什么风险?

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

AtomicInteger 核心操作的实现原理?

创建实例

    /**
* 可原子更新的 int 值
*/
private volatile int value; /**
* 创建初始值为 initialValue 的新 AtomicInteger 实例
*/
public AtomicInteger(int initialValue) {
value = initialValue;
} /**
* 创建初始值为 0 的新 AtomicInteger 实例
*/
public AtomicInteger() {
}

尝试以原子的方式更新值

    /**
* 如果当前值 == 预期值,则以原子方式将当前值设置为给定的更新值
* with memory effects as specified by {@link VarHandle#compareAndSet}.
*/
public final boolean compareAndSet(int expectedValue, int newValue) {
return U.compareAndSetInt(this, AtomicInteger.VALUE, expectedValue, newValue);
}

读取值

    /**
* 读取值
* with memory effects as specified by {@link VarHandle#getVolatile}.
*/
public final int get() {
return value;
}

以原子方式将当前值加 1,并返回旧值

    /**
* 以原子方式将当前值加 1,并返回旧值。
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*/
public final int getAndIncrement() {
return U.getAndAddInt(this, AtomicInteger.VALUE, 1);
} Unsafe#
/**
* 1)原子地将给定的值累加到当前值、或指定索引为 offset 的数组元素上。
*/
@HotSpotIntrinsicCandidate
public int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
// 以 volatile 的方式读取值
v = getIntVolatile(o, offset);
} while (!weakCompareAndSetInt(o, offset, v, v + delta));
// 返回旧值
return v;
} @HotSpotIntrinsicCandidate
public boolean weakCompareAndSetInt(Object o, long offset,
int expected,
int x) {
return compareAndSetInt(o, offset, expected, x);
} /**
* 如果当前值是 expected,则将目标值更新为 x,该操作具有 volatile 读和写内存语义。
* <p>This operation has memory semantics of a {@code volatile} read
* and write. Corresponds to C11 atomic_compare_exchange_strong.
*/
@HotSpotIntrinsicCandidate
public native boolean compareAndSetInt(Object o, long offset,
int expected,
int x);

以原子方式写入新值,并返回旧值

    /**
* 以原子方式写入新值,并返回旧值
* with memory effects as specified by {@link VarHandle#getAndSet}.
*/
public final int getAndSet(int newValue) {
return U.getAndSetInt(this, AtomicInteger.VALUE, newValue);
}

以原子方式将当前值减 1,并返回旧值

    /**
* 以原子方式将当前值减 1,并返回旧值
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*/
public final int getAndDecrement() {
return U.getAndAddInt(this, AtomicInteger.VALUE, -1);
}

以原子方式将给定值与当前值相加,并返回旧值

    /**
* 以原子方式将给定值与当前值相加,并返回旧值
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*/
public final int getAndAdd(int delta) {
return U.getAndAddInt(this, AtomicInteger.VALUE, delta);
}

原子更新当前值为函数式接口 updateFunction 的计算值,并返回旧值

    /**
* 原子更新当前值为函数式接口 updateFunction 的计算值,并返回旧值。
*/
public final int getAndUpdate(IntUnaryOperator updateFunction) {
// 读取旧值
int prev = get(), next = 0;
for (boolean haveNext = false;;) {
if (!haveNext) {
// 计算新值
next = updateFunction.applyAsInt(prev);
}
// 原子更新值,如果成功则返回旧值
if (weakCompareAndSetVolatile(prev, next)) {
return prev;
}
// 更新失败则重新读取旧值,如果出现 ABA 问题,则不会重新计算
haveNext = prev == (prev = get());
}
}

原子更新当前值为函数式接口 accumulatorFunction 的计算值,并返回旧值

    /**
* 原子更新当前值为函数式接口 accumulatorFunction 的计算值,并返回旧值
*/
public final int getAndAccumulate(int x,
IntBinaryOperator accumulatorFunction) {
// 读取旧值
int prev = get(), next = 0;
for (boolean haveNext = false;;) {
if (!haveNext) {
// 基于旧值和 x 计算新值
next = accumulatorFunction.applyAsInt(prev, x);
}
// 原子更新旧值
if (weakCompareAndSetVolatile(prev, next)) {
return prev;
}
haveNext = prev == (prev = get());
}
}

以原子方式将当前值加 1,并返回新值

    /**
* 以原子方式将当前值加 1,并返回新值
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*/
public final int incrementAndGet() {
return U.getAndAddInt(this, AtomicInteger.VALUE, 1) + 1;
}

以原子方式将当前值减 1,并返回新值

    /**
* 以原子方式将当前值减 1,并返回新值
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*/
public final int decrementAndGet() {
return U.getAndAddInt(this, AtomicInteger.VALUE, -1) - 1;
}

以原子方式将给定值与当前值相加,并返回新值

    /**
* 以原子方式将给定值与当前值相加,并返回新值
* with memory effects as specified by {@link VarHandle#getAndAdd}.
*/
public final int addAndGet(int delta) {
return U.getAndAddInt(this, AtomicInteger.VALUE, delta) + delta;
}

以原子方式更新值【新值通过函数式接口计算得到,参数为旧值】,并返回新值

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

以原子方式更新值【新值通过函数式接口计算得到,参数为旧值和参考更新值】,并返回新值

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

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

  1. AtomicInteger源码分析——基于CAS的乐观锁实现

    AtomicInteger源码分析——基于CAS的乐观锁实现 1. 悲观锁与乐观锁 我们都知道,cpu是时分复用的,也就是把cpu的时间片,分配给不同的thread/process轮流执行,时间片与时 ...

  2. JDK AtomicInteger 源码分析

    @(JDK)[AtomicInteger] JDK AtomicInteger 源码分析 Unsafe 实例化 Unsafe在创建实例的时候,不能仅仅通过new Unsafe()或者Unsafe.ge ...

  3. 并发-AtomicInteger源码分析—基于CAS的乐观锁实现

    AtomicInteger源码分析—基于CAS的乐观锁实现 参考: http://www.importnew.com/22078.html https://www.cnblogs.com/mantu/ ...

  4. 死磕 java并发包之AtomicInteger源码分析

    问题 (1)什么是原子操作? (2)原子操作和数据库的ACID有啥关系? (3)AtomicInteger是怎么实现原子操作的? (4)AtomicInteger是有什么缺点? 简介 AtomicIn ...

  5. AtomicInteger源码分析

    问题背景 最近在看LinkedBlockingQueue看到了其中的count使用AtomicInteger修饰,之前也看过AtomicInteger的一些解释,也是似懂非懂的,今天深入的了解了其实现 ...

  6. AtomicInteger源码分析——基于CAS的乐观锁实

    1. 悲观锁与乐观锁 我们都知道,cpu是时分复用的,也就是把cpu的时间片,分配给不同的thread/process轮流执行,时间片与时间片之间,需要进行cpu切换,也就是会发生进程的切换.切换涉及 ...

  7. 【Java】CAS的乐观锁实现之AtomicInteger源码分析

    1. 悲观锁与乐观锁 我们都知道,cpu是时分复用的,也就是把cpu的时间片,分配给不同的thread/process轮流执行,时间片与时间片之间,需要进行cpu切换,也就是会发生进程的切换.切换涉及 ...

  8. JDK源码分析-AtomicInteger

    AtomicInteger可以看做Integer类的原子操作工具类.在java.util.concurrent.atomic包下,在一些使用场合下可以取代加锁操作提高并发性.接下来就从几个方面来介绍: ...

  9. AtomicInteger原理&源码分析

    转自https://www.cnblogs.com/rever/p/8215743.html 深入解析Java AtomicInteger原子类型 在进行并发编程的时候我们需要确保程序在被多个线程并发 ...

随机推荐

  1. PY个树状数组

    树状数组看起来比较简单,于是就挑它下手了... 于是生活终于也对咱下手了... 要讲的就两个东西,一个是开数组,全局变量写最前面,数组是这么开的: f=[0 for i in range(500005 ...

  2. dsu on tree 与长链剖分

    dsu on tree 对于树进行轻重链剖分,对于节点 $x$ ,递归所有轻儿子后消除其影响,递归重儿子,不消除其影响. 然后对于所有轻儿子的子树暴力,从而得到 $x$ 的答案. 对于要消除暴力消除即 ...

  3. Quartz.NET | 佳佳的博客

    原文:Quartz.NET | 佳佳的博客 Quartz.NET 是一个定时计划任务的框架,支持 .NET Core. 本文示例代码大部分来自于官方教程:Quartz.NET - Quartz.NET ...

  4. vue.js table组件封装

    table组件 和 分页组件来自iview,在这里我根据公司业务再次做了一次封装,使用slot进行内容分发,可以随意放置input输入框和button按钮 ,再使用props向子组件传递参数,使用em ...

  5. keras数据增强

    1.keras数据增强:https://www.cnblogs.com/hutao722/p/10075150.html 2 .keras fit 中的 verbose verbose:日志显示ver ...

  6. evpp::buffer使用

    evpp::Buffer testmsg; const char* buf123 = "12342333333333333333333333333323424324234234"; ...

  7. apply_nodes_func

    import torch as th import dgl g=dgl.DGLGraph() g.add_nodes(3) g.ndata["x"]=th.ones(3,4) #n ...

  8. springboot中常用注解总结

    1.@RestController(组合注解):标注在类上,等价于@Controller和@Responsebody @Controller:将该类标记为Controller层的类,并且注入到Spri ...

  9. [Comet OJ - Contest #9 & X Round 3] Namid[A]me

    传送门 一开始读错题了,以为是\(\sum_{1\leq u\leq v\leq n}f(u,v)\),还疑惑这题这么简单怎么没人做( 实际上是\(\sum_{1\leq u\leq v\leq n} ...

  10. php-fpm参数优化

    php-fpm参数优化 2013-11-18 Posted by yeho php-fpm进程设置多少合适,设成动态还是静态? <lnmp一键安装包>中会根据你服务器内存调整php-fpm ...