原子类是 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();
使用场景:
与原子基本数据类型相比,专门用来执行累加操作,性能更好