AtomicInteger源码分析
Top:带着问题看源码
在这周之前对原子类毫无了解,前面看了Unsafe类,对CAS操作有了一点了解。所以看AtomicInteger时的问题很简单,弄清楚它是什么类,有什么作用。
参考:
彤哥读源码
https://mp.weixin.qq.com/s/DdwSC5bYgFCWwnb0jxkspg
一:简介
AtomicInteger是java并发包下面提供的原子类,主要操作的是int类型的整型,通过调用底层Unsafe的CAS等方法实现原子操作。
原子操作
原子操作是指不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何线程上下文切换。
原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分,将整个操作视作一个整体是原子性的核心特征。
我们这里说的原子操作与数据库ACID中的原子性,彤哥认为,数据库中的原子性主要运用在事务中,一个事务之内的所有更新操作要么都成功,要么都失败,事务是有回滚机制的,而这里说的原子操作是没有回滚的,这是最大的区别。
二:源码解析
总的来说,源码还是很简单的,很容易理解。提供原子操作主要是利用Unsafe类中的CAS方法。
属性
// 获取Unsafe实例
private static final Unsafe unsafe = Unsafe.getUnsafe();
// 标识value字段的偏移量,用来寻找
private static final long valueOffset;
// 静态代码块,通过unsafe获取value的偏移量
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// 存储int类型值的地方,使用volatile修饰
private volatile int value;
(1)使用int类型的value存储值,且使用volatile修饰,volatile主要是保证可见性,即一个线程修改对另一个线程立即可见,主要的实现原理是内存屏障,这里不展开来讲,有兴趣的可以自行查阅相关资料。
(2)调用Unsafe的objectFieldOffset()方法获取value字段在类中的偏移量,用于后面CAS操作时使用。
方法
构造方法和没有使用cas的get和set方法
public AtomicInteger(int initialValue) {
value = initialValue;
}
public AtomicInteger() {
}
public final int get() {
return value;
}
public final void set(int newValue) {
value = newValue;
}
通过Unsafe实现的set方法
// 调用putOrderedInt方法,有序写入,不保证原子性
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
}
// 最终通过CAS方法赋值
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
// 直接调用
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
// 没看出来和上一个语句的差别
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
自增自减以及加减的原子操作方法
// 自增1,调用unsafe的getAndAddInt方法,而unsafe中这个方法是调用CAS方法完成。返回未增加1时的值
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
// 自减1,同上
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
// 加上给定值,同上
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
// 自增1,返回加1后的值
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
// 自减1,返回减1后的值
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}
// 加上一个值,返回操作后的值。
public final int addAndGet(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
}
三:总结
(1)AtomicInteger中维护了一个使用volatile修饰的变量value,保证可见性;
(2)AtomicInteger中的主要方法最终几乎都会调用到Unsafe的compareAndSwapInt()方法保证对变量修改的原子性。
来源:CSDN
作者:Asia_Wyz
链接:https://blog.csdn.net/weixin_42183401/article/details/103706270