本文共 2119 字,大约阅读时间需要 7 分钟。
前言
AtomicInteger的本质:自旋锁+CAS原子操作
1. 源码分析
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 关键字
1.1 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);}
1.获取volatitle修饰的变量,最新的主存值
2.value+1作为自增值
3. compare value是否就是主存值,是,set next,return next;否,循环下一次
1.2 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私有的我们不能调用
2. 优缺点
AtomicInteger的优点
1.乐观锁,性能较强,利用CPU自身的特性保证原子性,即CPU的指令集封装compare and swap两个操作为一个指令来保证原子性。
2.适合读多写少模式
但是缺点明显
1.自旋,消耗CPU性能,所以写的操作较多推荐sync
2.仅适合简单的运算,否则会产生ABA问题,自旋的时候,别的线程可能更改value,然后又改回来,此时需要加版本号解决,JDK提供了AtomicStampedReference和AtomicMarkableReference解决ABA问题,提供基本数据类型和引用数据类型版本号支持
转载地址:http://mslvd.baihongyu.com/