前言
AtomicInteger的本质:自旋锁+CAS原子操作+volatile
一、源码分析
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;
使用Unsafe类,定义偏移量 valueOffset,类加载就初始化。用于原子操作CAS。
Unsafe类使Java拥有了像C语言的指针一样操作内存空间的能力,同时也带来了指针的问题。
AtomicInteger的本质 int value,私有的
这里要注意使用了volatile修饰,volatile 关键字
JDK1.7及以前
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);
}
- 获取volatitle修饰的变量,最新的主存值
- value+1作为自增值
- 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;
}
下面看getAndAddInt方法
public final int getAndAddInt(Object obj, long valueOffset, int delta) {
int expect;
//自旋
do {
//获取主存的值
expect = this.getIntVolatile(obj, valueOffset);
//CAS操作
} while(!this.compareAndSwapInt(obj, valueOffset, expect, expect + delta));
//返回旧值
return expect;
}
封装了自旋锁
直接封装unsafe方法中了,保证原子性,unsafe是JDK私有的我们不能调用
二、优缺点
1、AtomicInteger的优点
- 乐观锁,性能较强,利用CPU自身的特性保证原子性,即CPU的指令集封装compare and swap两个操作为一个指令来保证原子性。
- 适合读多写少模式
2、缺点
- 自旋,消耗CPU性能,所以写的操作较多推荐sync
- 仅适合简单的运算,否则会产生ABA问题,自旋的时候,别的线程可能更改value,然后又改回来,此时需要加版本号解决,JDK提供了AtomicStampedReference和AtomicMarkableReference解决ABA问题,提供基本数据类型和引用数据类型版本号支持
版权声明:本文为优快云博主「fenglllle」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/fenglllle/article/details/81316346