Java AtomicIntegerFieldUpdater, AtomicLongFieldUpdater 和 AtomicReferenceFieldUpdater
见名知意,FieldUpdater 就是以原子的方式更新字段的工具。
有两个关键点:
- 基于反射是实现,说明性能不够优秀。不合适在大流量的逻辑上使用。
- 对于需要原子更新的字段,只有该字段所有访问操作都经 FieldUpdater 完成,才能保证操作的原子性。
无关紧要的一点,字段必须是 volatile 修饰的。不过,如果不是的话会直接报错,所以没记住这点也无所谓了。
Java 提供了4个 AtomicFieldUpdater,分别是:
- AtomicIntegerFieldUpdater: 更新 Integer 字段
- AtomicLongFieldUpdater: 更新 Long 字段
- AtomicReferenceFieldUpdater: 更新引用字段的
AtomicIntegerFieldUpdater 和 AtomicLongFieldUpdater
AtomicIntegerFieldUpdater 和 AtomicLongFieldUpdater 是最简单的两个类。 使用上非常简单,就不详细说明了。
public class Main {
public static void main(String[] args) {
AtomicIntegerFieldUpdater<Number> updater = AtomicIntegerFieldUpdater.newUpdater(Number.class, "value");
Number number = new Number();
updater.compareAndSet(number, 0, 1);
}
public static class Number {
private volatile int value;
}
}
- 该类是一个泛型类,需要
<>
指定类型 - 该类通过
AtomicIntegerFieldUpdater#newUpdater
构造,入参为类型和字段名。该方法会做 volatile 检查。如果字段不是 volatile 修饰的,会报错。 - 该类通过 compareAndSet (CAS) 操作实现更新。其内部实现是通过 Unsafe 类的
compareAndSetInt()
完成。实在无需多言。
AtomicReferenceFieldUpdater
AtomicReferenceFieldUpdater 稍有不同,需要额外提供字段的类型。不过大差不差吧。
内部同样使用 Unsafe 的 compareAndSetReference()
方法实现。
public class Main {
public static void main(String[] args) {
AtomicReferenceFieldUpdater<Number, Integer> updater = AtomicReferenceFieldUpdater.newUpdater(Number.class, Integer.class, "value");
Number number = new Number();
Integer oldRef = number.value;
updater.compareAndSet(number, oldRef, 2333);
}
public static class Number {
private volatile Integer value;
}
}
总结
好鸡肋啊...