作者:蒲哟独CrRz | 来源:互联网 | 2023-10-15 15:42
AtomicInteger
内部调用了Unsafe的方法,保证原子性;
什么是原子性:指操作要么成功要么失败(失败则进行事务回滚)
从一个例子从开始学习AtomicInteger
Executor executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
for (int j = 0; j < 30; j++) {
a++;
System.out.println(atomicInteger.incrementAndGet());
}
});
}
其中a的值最终小于300,而atomicInteger最终输出的值为300(顺序不定)。
a++其实可以分解成3个步骤:
- 从主存读取a
- a+1操作
- 将结果刷新到主存
而在多线程中,某一线程进行了a+1但是值还没刷新到主存中另一个线程又执行了读取的操作,从而导致最终的结果小于300,而atomicInteger则不存在此风险,下面分析它为什么不存在此风险。
我们看其主要的变量以及常用的API来分析它内部是如何实现的:
变量
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long VALUE;
static {
try {
VALUE = U.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
private volatile int value;
常用API
从例子中的方法开始分析:
public final int incrementAndGet() {
return U.getAndAddInt(this, VALUE, 1) + 1;
}
public final int getAndAddInt(Object obj, long offset, int increment) {
int value;
do {
value = this.getIntVolatile(obj, offset);
} while(!this.compareAndSwapInt(obj, offset, value, value + increment));
return value;
}
其他常用的API与之类似,核心都是调用Unsafe中的native方法