前言
AtomicInteger使得在高并发的场景下,可以安全的操作整数的增减。主要原理是采用Unsafe.CAS操作。
原子操作类
多线程同时对int i
进行操作,可能导致原子性问题。
可以加Synchronized悲观锁解决,考虑到性能问题,JDK1.5后,J.U.C包提供Atomic包 → 对常用数据结构做原子操作。
J.U.C中的原子操作类有:
- 原子基本类型
- AtomicBoolean、 AtomicInteger、 AtomicLong
- 原子数组
- AtomicIntegerArray 、 AtomicLongArray 、AtomicReferenceArray
- 原子引用
- AtomicReference 、 AtomicReferenceFieldUpdater 、AtomicMarkableReference(更新带有标记位的引用类型)
- 原子字段
- AtomicIntegerFieldUpdater、 AtomicLongFieldUpdater、AtomicStampedReference
AtomicInteger源码分析
接下来,我们一起来看AtomicInteger源码:
getAndIncrement方法
调用Unsafe类中的方法。
Unsafe类相当于Java的后门,使得Java可以像C语言一样直接操作内存空间。当然也会带来弊端 → 指针问题。除了J.U.C包外,Netty、Kafka也使用这个类。这个类提供了很多功能,包括:多线程同步(monitorEnter)、CAS操作(compareAndSwap)、线程的挂起和恢复(park/unpark)、内存屏障(loadFence/storeFence)、内存管理(内存分配、释放内存、获取内存地址等)。
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);//每次增加1
}
valueOffset
→ 当前Value变量在内存中的偏移量
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
Unsafe.getAndAddInt
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
//从主内存中获取当前value
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
get方法
get()
只需要返回value值就行,这里的value是通过volatile修饰的。
public final int get() {
return value;
}
compareAndSet方法
compareAndSet()
允许客户端基于AtomicInteger实现乐观锁操作。
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}