Java原子类简述


一、概述

java的java.util.concurrent包除了提供底层锁、并发集合外,还提供了一组原子操作的封装类,它们位于java.util.concurrent.atomic包。

Atomic类是通过无锁(lock-free)的方式实现的线程安全(thread-safe)访问

二、原子类是基于什么实现的

原子类的实现是基于CPU本身提供的CAS指令,是一种无锁的实现;

CAS(Compare and Swap)比较并交换,即在更新之前会校验是否于期待的值相等

执行函数:CAS(V,E,N)

V表示要更新的变量;E表示预期值;N表示新值

CAS容易出现ABA问题

容易出现在原子变量值不确定容易反复的情况

假设count原本是A线程1检查数值 期望值为A,未执行更新操作,此时线程2更新值为B线程3更新值为A,然后线程1执行更新操作 ,期望值与实际值相同执行操作。
解决方案:类似乐观锁,加上版本号。

三、常用的原子类

1. 基本类型

使用原子的方式更新基本类型

原子类 类型
整形原子类
AtomicLong 长整型原子类
AtomicBoolean 布尔型原子类

2. 引用类型

原子类 类型
引用类型原子类
原子更新引用类型里的字段原子类
原子更新带有标记位的引用类型

ABA 问题

AtomicStampedReferenceAtomicMarkableReference这两个原子类可以解决ABA问题。

AtomicStampedReference该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用CAS进行原子更新时可能出现的ABA问题。

3. 数组类型

原子类 类型
整形数组原子类
AtomicLongArray 长整形数组原子类
AtomicReferenceArray 引用类型数组原子类

这些类提供的方法和原子化的基本数据类型 的区别仅仅是:每个方法多了一个数组的索引参数,所以这里也不再赘述了。

4. 对象属性更新器

原子类 类型
AtomicIntegerFieldUpdater 原子更新整形的更新器
AtomicLongFieldUpdater 原子更新长整形的更新器
原子更新引用的更新器

利用它们可以原子化地更新对象的属性,这三个方法都是利用反射机制实现的。

5. 累加器

原子类 类型
DoubleAccumulator 原子更新整形字段的更新器
DoubleAdder 原子更新长整形字段的更新器
LongAccumulator 原子更新长整形字段的更新器
原子更新长整形字段的更新器

LongAccumulator是LongAdder的功能增强版,LongAdder的API只有对数值的加减,而LongAccumulator提供了自定义的函数操作。

这四个类仅仅用来执行累加操作,相比原子化的基本数据类型,速度更快,但是不支持compareAndSet()方法。如果仅仅需要累加操作,使用原子化的累加器性能会更好

四、原子类的用途

适用于计数器,累加器等场景(更推荐redis)

参考文章

  • 原子类
JUC