AtomicInteger原理分析
程序员文章站
2022-07-13 14:51:15
...
看源码
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value;
AtomicInteger的本质 int value,私有的
这里要注意使用了volatile修饰,volatile 关键字
在JDK1.7及以前使用Java代码实现的自增
public final int incrementAndGet() {
for (;;) {
//获取volatitle修饰的变量,最新的主存值
int current = get();
//理论上自增值
int next = current + 1;
//比对,自旋
if (compareAndSet(current, next))
return next;
}
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
1.获取volatitle修饰的变量,最新的主存值
2.value+1作为自增值
3. compare value是否就是主存值,是,set next,return next;否,循环下一次
在JDK1.8及以后
/**
* Atomically increments by one the current value.
*
* @return the updated value
*/
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
直接封装unsafe方法中了,保证原子性,unsafe是JDK私有的我们不能调用
AtomicInteger的优点
1.乐观锁,性能较强,利用CPU自身的特性保证原子性,即CPU的指令集封装compare and swap两个操作为一个指令来保证原子性。
2.适合读多写少模式
但是缺点明显
1.自旋,消耗CPU性能,所以写的操作较多推荐sync
2.仅适合简单的运算,否则会产生ABA问题,自旋的时候,别的线程可能更改value,然后又改回来,此时需要加版本号解决,JDK提供了AtomicStampedReference和AtomicMarkableReference解决ABA问题,提供基本数据类型和引用数据类型版本号支持
号外,ThreadPoolExecutor大量引用了CAS特性