IMLC.ME

Java AtomicIntegerFieldUpdater, AtomicLongFieldUpdater 和 AtomicReferenceFieldUpdater

见名知意,FieldUpdater 就是以原子的方式更新字段的工具。

有两个关键点:

  1. 基于反射是实现,说明性能不够优秀。不合适在大流量的逻辑上使用。
  2. 对于需要原子更新的字段,只有该字段所有访问操作都经 FieldUpdater 完成,才能保证操作的原子性。

无关紧要的一点,字段必须是 volatile 修饰的。不过,如果不是的话会直接报错,所以没记住这点也无所谓了。

Java 提供了4个 AtomicFieldUpdater,分别是:

  1. AtomicIntegerFieldUpdater: 更新 Integer 字段
  2. AtomicLongFieldUpdater: 更新 Long 字段
  3. 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;
    }

}
  1. 该类是一个泛型类,需要 <> 指定类型
  2. 该类通过 AtomicIntegerFieldUpdater#newUpdater 构造,入参为类型和字段名。该方法会做 volatile 检查。如果字段不是 volatile 修饰的,会报错。
  3. 该类通过 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;
    }
}

总结

好鸡肋啊...