Atomic包
Atomic包描述
以AtomicInteger
为例。在AtomicInteger
中有一个volatile修饰的value
变量,也就是这个整型的值。在调用getAndIncrement()
时,AtomicInteger
会通过Unsafe
类的getAndAddInt
方法对变量value
进行一次CAS[1]操作。由于CAS是具有原子性的,所以AtomicInteger就保证了操作的线程安全
Atomic包主要提供四种原子更新方式
- 原子方式更新基本数据类型
- AtomicBoolean:原子更新布尔类型
- AtomicInteger:原子更新整型
- AtomicLong:原子更新长整型
- 原子方式更新数组
- AtomicIntegerArray:原子更新整型数组里的元素
- AtomicLongArray:原子更新长整型数组里的元素
- AtomicReferenceArray:原子更新引用类型数组里的元素
- 原子方式更新引用
- AtomicReference:原子更新引用类型
- AtomicReferenceFieldUpdater:原子更新引用类型里的字段
- AtomicMarkableReference:原子更新带有标记位的引用类型
- 原子方式更新字段
- AtomicIntegerFieldUpdater:原子更新整型字段的更新器
- AtomicLongFieldUpdater:原子更新长整型字段的更新器
- AtomicStampedReference:原子更新带有版本号的引用类型,用于解决使用CAS进行原子更新时,可能出现的ABA问题
- 计数器
- DoubleAccumulator:更通用,能自定义函数
- DoubleAdder:累加器
- LongAccumulator:更通用,能自定义函数
- LongAdder:累加器
Atomic包提供了三种基本类型的原子更新,但是Java的基本类型里还有char,float和double等。如何原子的更新其他的基本类型呢?Atomic包里的类基本都是使用Unsafe实现的,Unsafe只提供了三种CAS方法,compareAndSwapObject,compareAndSwapInt和compareAndSwapLong,AtomicBoolean是先把Boolean转换成整型,再使用compareAndSwapInt进行CAS,所以原子更新double也可以用类似的思路来实现
LongAdder LongAccumulator DoubleAdder DoubleAccumulator 的适用场景
第一点需要满足的条件,就是需要大量的计算,并且当需要并行计算的时候,我们可以考虑使用 LongAccumulator。
当计算量不大,或者串行计算就可以满足需求的时候,可以使用 for 循环;如果计算量大,需要提高计算的效率时,我们则可以利用线程池,再加上 LongAccumulator 来配合的话,就可以达到并行计算的效果,效率非常高。