AtomicInteger阅读笔记
问题
1、什么是原子操作?
- 一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样
2、什么是可见性?
- 可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
3、AtomicInteger通过什么实现原子操作?
- 通过Unsafe原子工具类来实现原子操作
4、AtomicInteger有什么缺点?
- 有ABA问题,且自旋消耗CPU性能
一、简介
优点:
- CAS乐观锁,性能较强,利用CPU自身的特性保证原子性,即CPU的指令集封装CompareAndSwap两个操作为一个指令来保证原子性。
- 适合读多写少模式。
缺点:
- 自旋,消耗CPU性能,所以写的操作较多推荐sync(悲观锁)
- 仅适合简单的运算,否则会 产生ABA问题,自旋的时候,别的线程可能更改value,然后又更改回来,此时需要加版本号解决,JDK提供了AtomicStampedReference和AtomicMarkableReference解决ABA问题,提供基本数据类型和引用数据类型版本号支持
二、继承关系图
1、继承Number抽象类、实现Serializable接口
2、函数列表
三、存储结构
- 支持并发的Integer存储结构,大部分都是final方法
四、源码分析
内部类
- 无
属性
- Unsafe:工具
- value:int值
- valueOffset:内存偏移地址
构造
public AtomicInteger()
- 实例化AtomicInteger
public AtomicInteger(int initialValue) {value = initialValue;}
- 实例化AtomicInteger 且初始化value。
主要方法
public final int getAndAdd(int delta){ return unsafe.getAndAddInt(this, valueOffset, delta);}
- 返回当前value,在内存中对value进行加delta,
public final int addAndGet(int delta){ return unsafe.getAndAddInt(this, valueOffset, delta) + delta;}
- 在内存中对value进行加delta,然后返回原value+delta的和。
public final int getAndDecrement(){ return unsafe.getAndAddInt(this, valueOffset, -1);}
- 返回当前value,然后对value-1,类似i–;
public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1);}
- 返回当然value,然后对value+1,类似i++;
public final int decrementAndGet() {return unsafe.getAndAddInt(this, valueOffset, -1) - 1;}
- 在内存中对value进行-1,然后返回的值,类似–i;
public final int incrementAndGet() {return unsafe.getAndAddInt(this,valueOffset, 1) + 1;}
- 在内存中对value进行+1,然后返回新的值,类似++i;
public final int getAndSet(int newValue) { return unsafe.getAndSetInt(this, valueOffset, newValue);}
- 返回当前value,然后把value更新为newValue,采用cas
public final void set(int newValue) {value = newValue;}
- 更新value为newValue。立即修改旧值,别的线程可以立马看到新值
public final void lazySet(int newValue){unsafe.putOrderedInt(this,valueOffset, newValue);}
- 更新value为newValue。不能保证其他线程能立即看到修改的值,但最终会看到
补充
//获取Unsafe工具
private static final Unsafe unsafe = Unsafe.getUnsafe();
//value值在AtomicInteger对象中的偏移量,用于读写操作
private static final long valueOffset;
static {
try {
//初始化valueOffset
//使用反射获得value字段的Field,然后调用unsafe工具类的objectFieldOffset(获取非静态属性在对象中的偏移量)。
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 {
var5 = this.getIntVolatile(var1, var2);//使用volatile方式获取值
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//循环更新值,失败继续
return var5;
}
五、总结
主要大量运用了Unsafe类。