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. 最长上升子序列(LIS) Medium2

    JGShining's kingdom consists of 2n(n is no more than 500,000) small cities which are located in two ...

  2. Vue 数据持久化

    方法一:使用 localStorage 存储数据 window.localStorage.setItem(key,value) 方法二:使用 vuex-persistedstate插件 vuex 存在 ...

  3. UITableViewCell选中后子View背景色被Clear

    在TableView中,当cell 处于Hightlighted(高亮)或者Selected(选中)状态下,Cell上的子控件的背景颜色会被 Clear. 解决方法:(4种) 1. 直接设置子控件的 ...

  4. 切入点表达式execution()

    用于描述方法 [掌握] 语法:execution(修饰符 返回值 包.类.方法名(参数) throws异常) 修饰符,一般省略 public                公共方法 *         ...

  5. Linux 开机自动启动脚本

    1)编写要执行脚本的sh文件mysetup.sh #!/bin/sh ### BEGIN INIT INFO # Provides: land.sh # Required-start: $local_ ...

  6. mock.js模拟ajax数据请求

    在我们开发过程中存在着前端页面ui完成了,但是没有接口进行联调数据的情况,现在介绍一下用mock.js来完成数据的请求.这样在后期我们的后台接口完成后只需要更改请求的接口名字即可!前提是你的模拟字段名 ...

  7. C++中vecotr表示二维数组并自己实现一个Grid类

    1 C++中使用vector来表示二维数组 声明一个二维数组: vector<vector<int>> dp(row, vector<int>(col)); 将变量 ...

  8. python set 集合操作

    转自:https://www.cnblogs.com/alex3714/articles/5740985.html s = set([3,5,9,10]) #创建一个数值集合 t = set(&quo ...

  9. H5 FormData对象

    FormData对象 2018年01月08日 14:31:53 阅读数:2635 FormData对象,可以把所有表单元素的name与value组成一个queryString,提交到后台. 在使用aj ...

  10. logback系列二:logback在项目中的应用

    1.输出http日志 2.输出dubbo日志 3.输出interfacer日志 4.输出到access,remote,app等目录中