JUC之原子操作类
基本类型原子类
- AtomicInteger
- AtomicBoolean
- AtomicLong
//获取当前的值
public final int get()
//获取当前的值,并设置新的值
public final int getAndSet(int newValue)
//获取当前的值,并自增
public final int getAndIncrement()
//获取当前的值,并自减
public final int getAndDecrement()
//获取当前的值,并加上预期的值
public final int getAndAdd(int delta)
//如果输入的数值等于预期值,则以原子方式将该值设置为输入值(update)
boolean compareAndSet(int expect, int update)
数组类型原子类
- AtomicIntegerArray
- AtomicLongArray
- AtomicReferenceArray
引用类型原子类
- AtomicReference
- AtomicStampedReference
- AtomicMarkableReference
- 它的定义就是将状态戳简化为true|false
对象属性原子类
- AtomicIntegerFieldUpdater
- 原子更新对象中int类型字段的值
- AtomicLongFieldUpdater
- 原子更新对象中Long类型字段的值
- AtomicReferenceFieldUpdater
- 原子更新引用类型字段的值
目的
以一种线程安全的方式操作非线程安全对象内的某些字段
要求
更新的对象属性必须使用 public volatile 修饰符
因为对象的属性修改类型原子类都是抽象类,所以每次使用都必须使用静态方法 newUpdater() 创建一个更新器,并且需要设置想要更新的类和属性
原子操作增强类
- DoubleAccumulator
- DoubleAdder
- LongAccumulator
- LongAdder
LongAdder为什么这么快
Striped64
LongAdder是Striped64的子类
Striped64重要的的成员函数
/** CPU数量,即cells数组的最大长度 */
static final int NCPU = Runtime.getRuntime().availableProcessors();
/** cells数组,为2的幂,2,4,8,16.....,方便以后位运算 */
transient volatile Cell[] cells;
/**基础value值,当并发较低时,只累加该值主要用于没有竞争的情况,通过CAS更新 */
transient volatile long base;
/**创建或者扩容Cells数组时使用的自旋锁变量调整单元格大小(扩容),创建单元格时使用的锁*/
transient volatile int cellsBusy;
LongAdder的基本思路就是分散热点,将value值分散到一个Cell数组中,不同线程会命中到数组的不同槽中,各个线程只对自己槽中的那个值进行CAS操作,这样热点就被分散了,冲突的概率就小很多。如果要获取真正的long值,只要将各个槽中的变量值累加返回
sum()会将所有Cell数组中的value和base累加作为返回值,核心的思想就是将之前AtomicLong一个value的更新压力分散到多个value中去,从而降级更新热点
LongAdder在无竞争的情况,跟AtomicLong一样,对同一个base进行操作,当出现竞争关系时则是采用化整为零的做法,从空间换时间,用一个数组cells,将一个value拆分进这个数组cells
多个线程需要同时对value进行操作时候,可以对线程id进行hash得到hash值,再根据hash值映射到这个数组cells的某个下标,再对该下标所对应的值进行自增操作。当所有线程操作完毕,将数组cells的所有值和无竞争值base都加起来作为最终结果
longAdder.increment() 过程
-
add 方法
- 最初无竞争时只更新 base
- 如果更新 base 失败后,首次新建一个Cell 数组
- 当多个线程竞争同一个 Cell 比较激烈时,可能就要对 Cell 扩容
-
longAccumulate 方法
-
sum 方法
- sum()会将所有 Cell 数组中的 value 和 base 累加作为返回值