「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战」。
原子类简介
-
原子类是 Java atomic 包中提供的一系列原子操作的类,大多以 Atomic 开头
-
原子类一种无锁方案,原理是使用 CAS 指令,因为不需要涉及到操作系统内核层面的加锁,性能很好
-
CAS 指令封装在 Unsafe 类的本地方法中,底层是硬件支持的 compare_exchange 指令
-
CAS 指令是先比较判断值是否更新,没更新就交换数据,有更新就循环尝试
示例代码模拟 CAS 和自旋操作
class Adder { private volatile int count; public void addOne() { // 存储一份当前值和 +1 后的值 int oldVal, newVal; do { oldVal = this.count; newVal = oldVal + 1; } while (!cas(oldVal, newVal)); } /** * 利用 synchronized 模拟原子的 CAS 操作 * * @param oldVal 旧值 * @param newVal 新值 * @return 比较旧值,没有更新才设置新值,返回 true */ private synchronized boolean cas(int oldVal, int newVal) { // 比较数据是否发生改变 if (oldVal == this.count) { this.count = newVal; return true; } return false; } }
原子类型
基本数据类型
-
原子类
有 AtomicBoolean、AtomicInteger 和 AtomicLong
-
常用 API
AtomicInteger integer = new AtomicInteger(); // i++ integer.getAndIncrement(); // --i integer.decrementAndGet(); // 加上指定值,返回加前的值 integer.getAndAdd(delta);
-
使用场景:
原子的更新一个基本数据类型
对象引用类型
-
原子类
有 AtomicReference、AtomicStampedReference 和 AtomicMarkableReference
-
常用 API
AtomicReference<User> atomicUser = new AtomicReference<>(); atomicUser.set(new User("张三", 20)); atomicUser.getAndAccumulate(new User("李四", 21), (user, user2) -> user);
-
使用场景:
原子的更新整个对象
AtomicStampedReference 和 AtomicMarkableReference 在更新时会添加版本号,可以解决 ABA 问题
对象属性更新器
-
原子类
有 AtomicIntegerFieldUpdater、AtomicLongFieldUpdater 和 AtomicReferenceFieldUpdater
-
常用 API
User user = new User("张三", 20); // 年龄更新器,age 属性需要声明为 volatile AtomicIntegerFieldUpdater<User> fieldUpdater = AtomicIntegerFieldUpdater.newUpdater(User.class, "age"); // 年龄加一 fieldUpdater.getAndAdd(user, 1);
-
使用场景:
原子的更新对象的某个属性
数组
-
原子类
有 AtomicIntegerArray、AtomicLongArray 和 AtomicReferenceArray
-
常用 API
AtomicIntegerArray array = new AtomicIntegerArray(1); // 下标 i 的元素,加上 delta array.addAndGet(i, delta)
-
使用场景:
原子的更新数组元素,和原子基本数据类型使用方式类似,方法参数需要转入索引
比原子基本数据类型的数组更节约空间
累加器
-
原子类
有 DoubleAccumulator、DoubleAdder、LongAccumulator 和 LongAdder
-
常用 API
LongAdder adder = new LongAdder(); // +1 adder.increment(); // 获取 int 值 adder.intValue();
-
使用场景:
与原子基本数据类型相比,专门用来执行累加操作,性能更好