五、原子类
2018-08-21 本文已影响0人
小绵羊你毛不多
原子类
为什么要用原子类
- 在volatile中提到,它是不能保证num++这种符合类操作的原子性问题。
- 只能用锁机制去解决,但是原子类更精巧轻量,性能开销更小。
原理
CAS(Compare-and-Swap)
- CAS包含三个操作数
- 内存值 V
- 预估值 A
- 更新值 B
当且仅当V==A时,V讲被赋值为B,否则循环判断V是否与A相等
- ABA问题
- 同时用m、n线程同时取出值为A,然后n更新成B,然后又更新成A,这时候m线程一样可以更新成功!但是中间这个值已经被更新过两次
- 如果链表的头在变化了两次后,恢复了原值,不代表链表就没有变化。
Atomic包主要提供四种原子更新方式
- 更新基本类型
- AtomicInteger、AtomicBoolean、AtomicLong
- AtomicInteger
public class AtomicInteger extends Number implements java.io.Serializable {
private static final Unsafe unsafe = Unsafe.getUnsafe();
public final int incrementAndGet() {
//为什么返回的时候 要再一次+1?看下面这个方法的返回值就知道了
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
}
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
//获取原来的值
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
//这里返回的是var5,也就是原来的值,更新后的值是var5+var4
return var5;
}
// 是一个native方法
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
- 更新数组
- AtomicIntegerArray
- AtomicLongArray
- AtomicReferenceArray
- 更新引用
- AtomicReference
- AtomicReferenceFieldUpdater 更新引用类型里的字段
- AtomicMarkableReference 更新带有标记位的引用类型
- 更新字段
- AtomicIntegeFieldUpdater
- AtomicLongFieldUpdater
- AtomicStampedReference 更新引用类型,带有版本号,解决ABA的问题。