java并发-AtomicInteger详解
2023-12-28 10:56:17
AtomicInteger
是Number
类的一个子类,它还提供了很多的原子性的操作方法。
1.构造方法
/**
*创建
*AtomicInteger并且指定初始值,无参的AtomicInteger对象创建
*等价于AtomicInteger(0)。
**/
public AtomicInteger(int initialValue) {
value = initialValue;
}
/**
* 创建AtomicInteger的初始值为0。
*/
public AtomicInteger() {
}
2.Incremental(增加)操作
int getAndIncrement()
:返回当前int类型的value值,然后对value进行自增运算。int incrementAndGet()
:直接返回自增后的结果,该操作方法能够确保对value的原子性增量操作。
3.Decremental(递减)操作
int getAndDecrement()
: 返回当前int类型的value值,然后对value进行自减运算。int decrementAndGet()
: 直接返回自减后的结果,该操作方法能够确保对value的原子性减量操作。
4.原子性地更新value值
boolean compareAndSet(int expect, int update)
:原子性地更新AtomicInteger
的值,其中expect
代表当前的AtomicInteger
数值,update
则是需要设置的新值,该方法会返回 一个boolean
的结果:当expect
和AtomicInteger
的当前值不相等时,修改会失败,返回值为false
;若修改成功则会返回true
。
// 定义一个AtomicInteger类型的对象ai并且指定初值为10
AtomicInteger ai = new AtomicInteger(10);
// 调用compareAndSet方法,expect的值为100,修改肯定会失败
assert !ai.compareAndSet(100, 12);
// 修改并未成功,因此新值不等于12
assert ai.get() != 12;
// 执行了compareAndSet更新方法之后,ai的返回值依然为10,因为修改失败
assert ai.get() == 10;
// 调用compareAndSet方法,expect的值为10,修改成功(多线程情况下并不能
担保百分之百成功,// 关于这一点,在2.1.3节中会为大家讲解)
assert ai.compareAndSet(10, 12);
// 断言成功
assert ai.get() == 12;
int getAndAdd(int delta)
: 原子性地更新AtomicInteger
的value
值,更新后的value
为value
和delta
之和,方法的返回值为value
的前一个值,该方法实际上是基于自旋+CAS算法实现的(Compare And Swap)原子性操作。
// 定义一个AtomicInteger类型的对象ai并且指定初始值为10
AtomicInteger ai = new AtomicInteger(10);
// 调用getAndAdd方法,返回value的前一个值为10
assert ai.getAndAdd(2) == 10;
// 调用get方法返回AtomicInteger的value值,当前返回值为12
assert ai.get() == 12;
int addAndGet(int delta)
: 该方法与getAndAdd(int delta)
一样,也是原子性地更新AtomicInteger
的value
值,更新后的结果value
为value
和delta
之和,但是该方法会立即返回更新后的value
值。
// 定义一个AtomicInteger类型的对象ai并且指定初始值为10
AtomicInteger ai = new AtomicInteger(10);
// 调用addAndGet方法,返回当前value的值
assert ai.addAndGet(2)==12;
// 调用get方法返回AtomicInteger的value值,当前返回值为12
assert ai.get() == 12;
5.函数式接口
int getAndUpdate(IntUnaryOperator updateFunction)
: 原子性地更新AtomicInteger
的值,方法入参为IntUnaryOperator
接口,返回值为value
更新之前的值。
// 定义一个AtomicInteger类型的对象ai并且指定初始值为10
AtomicInteger ai = new AtomicInteger(10);
// 调用getAndUpdate方法并且传入lambda表达式,返回结果为value的前一个值
assert ai.getAndUpdate(x -> x + 2) == 10;
// 调用get方法返回AtomicInteger的value值,当前返回值为12
assert ai.get() == 12;
int updateAndGet(IntUnaryOperator updateFunction)
: 原 子性地更新AtomicInteger
的值,方法入参为IntUnaryOperator
接口,该方法会立即返回更新后的value
值。
// 定义一个AtomicInteger类型的对象ai并且指定初始值为10
AtomicInteger ai = new AtomicInteger(10);
// 调用updateAndGet方法并且传入lambda表达式,返回结果为value更新后的值
assert ai.updateAndGet(x -> x + 2) == 12;
// 调用get方法返回AtomicInteger的value值,当前返回值为12
assert ai.get() == 12;
int getAndAccumulate(int x, IntBinaryOperator accumulatorFunction)
:原子性地更新AtomicInteger
的值,方法入参为IntBinaryOperator
接口和delta
值x
,返回值为value
更新之前的值。
// 定义一个AtomicInteger类型的对象ai并且指定初值为10
AtomicInteger ai = new AtomicInteger(10);
int result = ai.getAndAccumulate(5, Integer::sum);
assert result == 10;
assert ai.get() == 15;
int accumulateAndGet(int x, IntBinaryOperator accumulatorFunction)
:该方法与getAndAccumulate
类似,只不过会立即返回AtomicInteger
的更新值。
// 定义一个AtomicInteger类型的对象ai并且指定初值为10
AtomicInteger ai = new AtomicInteger(10);
int result = ai.accumulateAndGet(5, Integer::sum);
assert result == 15;
assert ai.get() == 15;
6.其他方法
void set(int newValue)
:为value
设置新值后其他线程就会立即看见。void lazySet(int newValue)
:被强制刷新到主内存中,从而立即被其他线程看到。int get()
: 返回AtomicInteger
的value
当前值。
7.源码分析
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
v = getIntVolatile(o, offset);
} while (!compareAndSwapInt(o, offset, v, v + delta));
return v;
}
通过上边源码很容易看出底层实现是通过cas和自旋的操作。
8.使用示例
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerExample {
public static void main(String[] args) {
// 创建一个初始值为0的AtomicInteger
AtomicInteger atomicInteger = new AtomicInteger(0);
// 创建并启动两个增加线程
Thread incrementThread1 = new Thread(new IncrementTask(atomicInteger));
Thread incrementThread2 = new Thread(new IncrementTask(atomicInteger));
incrementThread1.start();
incrementThread2.start();
try {
// 等待两个线程执行完成
incrementThread1.join();
incrementThread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印最终结果
System.out.println("Final Value: " + atomicInteger.get());
}
// 自增任务
static class IncrementTask implements Runnable {
private AtomicInteger atomicInteger;
public IncrementTask(AtomicInteger atomicInteger) {
this.atomicInteger = atomicInteger;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
// 使用原子操作自增
atomicInteger.incrementAndGet();
}
}
}
}
运行结果:
Final Value: 2000
9.总结
本文介绍了AtomicInteger
相关的方法,通过源码很明显看出AtomicInteger
底层是通过cas+自旋实现。
文章来源:https://blog.csdn.net/qq_36649893/article/details/135258017
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!