Java
Java多线程
JUC相关

Java多线程 14 - AtomicLongFieldUpdater详解

简介:AtomicLongFieldUpdater可以对指定类的volatile long类型的成员进行原子更新它是基于反射原理实现的。

1. AtomicLongFieldUpdater详解

AtomicLongFieldUpdater可以对指定类的volatile long类型的成员进行原子更新它是基于反射原理实现的。在用法上有规则:

  • 字段必须是volatile类型的,在线程之间共享变量时保证立即可见。
  • 字段的描述类型(修饰符public / protected / default / private)是与调用者与操作对象字段的关系一致。也就是说调用者能够直接操作对象字段,那么就可以反射进行原子操作。
  • 对于父类的字段,子类是不能直接操作的,尽管子类可以访问父类的字段。
  • 只能是实例变量,不能是类变量,也就是说不能加static关键字。
  • 只能是可修改变量,不能使final变量,因为final的语义就是不可修改。
  • 对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装类型(Integer/Long)。如果要修改包装类型就需要使用AtomicReferenceFieldUpdater。

1.1. AtomicLongFieldUpdater API列表

  • // 受保护的无操作构造方法,供子类使用
  • protected AtomicLongFieldUpdater()
  • // 以原子方式将给定值添加到此更新器管理的给定对象的字段的当前值
  • long addAndGet(T obj, long delta)
  • // 如果当前值等于预期值,则以原子方式将此更新器所管理的给定对象的字段设置为给定的更新值
  • abstract boolean compareAndSet(T obj, long expect, long update)
  • // 以原子方式将此更新器管理的给定对象字段当前值减1
  • long decrementAndGet(T obj)
  • // 获取此更新器管理的在给定对象的字段中保持的当前值
  • abstract long get(T obj)
  • // 以原子方式将给定值添加到此更新器管理的给定对象的字段的当前值
  • long getAndAdd(T obj, long delta)
  • // 以原子方式将此更新器管理的给定对象字段当前值减1
  • long getAndDecrement(T obj)
  • // 以原子方式将此更新器管理的给定对象字段的当前值加1
  • long getAndIncrement(T obj)
  • // 将此更新器管理的给定对象的字段以原子方式设置为给定值,并返回旧值
  • long getAndSet(T obj, long newValue)
  • // 以原子方式将此更新器管理的给定对象字段当前值加1
  • long incrementAndGet(T obj)
  • // 最后将此更新器管理的给定对象的字段设置为给定更新值
  • abstract void lazySet(T obj, long newValue)
  • // 为对象创建并返回一个具有给定字段的更新器
  • static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName)
  • // 将此更新器管理的给定对象的字段设置为给定更新值
  • abstract void set(T obj, long newValue)
  • // 如果当前值等于预期值,则以原子方式将此更新器所管理的给定对象的字段设置为给定的更新值
  • abstract boolean weakCompareAndSet(T obj, long expect, long update)

2. AtomicLongFieldUpdater源码解析

AtomicLongFieldUpdater源码源码如下(基于JDK 1.8.0_101):

  • package java.util.concurrent.atomic;
  • import java.lang.reflect.Field;
  • import java.lang.reflect.Modifier;
  • import java.security.AccessController;
  • import java.security.PrivilegedActionException;
  • import java.security.PrivilegedExceptionAction;
  • import java.util.Objects;
  • import java.util.function.LongBinaryOperator;
  • import java.util.function.LongUnaryOperator;
  • import sun.reflect.CallerSensitive;
  • import sun.reflect.Reflection;
  • public abstract class AtomicLongFieldUpdater<T> {
  • // 针对某个类的某个字段创建一个updater更新器,会对传入的类和字段使用反射检查类型是否匹配
  • @CallerSensitive
  • public static <U> java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
  • Class<?> caller = Reflection.getCallerClass();
  • if (AtomicLong.VM_SUPPORTS_LONG_CAS)
  • return new java.util.concurrent.atomic.AtomicLongFieldUpdater.CASUpdater<U>(tclass, fieldName, caller);
  • else
  • return new java.util.concurrent.atomic.AtomicLongFieldUpdater.LockedUpdater<U>(tclass, fieldName, caller);
  • }
  • // 保护构造方法
  • protected AtomicLongFieldUpdater() {
  • }
  • // 如果当前值等于预期值,则以原子方式将此更新器所管理的给定对象的字段设置为给定的更新值
  • public abstract boolean compareAndSet(T obj, long expect, long update);
  • //
  • public abstract boolean weakCompareAndSet(T obj, long expect, long update);
  • // 将此更新器管理的给定对象的字段设置为给定更新值
  • public abstract void set(T obj, long newValue);
  • //
  • public abstract void lazySet(T obj, long newValue);
  • // 获取此更新器管理的在给定对象的字段中保持的当前值
  • public abstract long get(T obj);
  • // 将此更新器管理的给定对象的字段以原子方式设置为给定值,并返回旧值
  • public long getAndSet(T obj, long newValue) {
  • long prev;
  • do {
  • prev = get(obj);
  • } while (!compareAndSet(obj, prev, newValue));
  • return prev;
  • }
  • // 以原子方式将此更新器管理的给定对象字段的当前值加1
  • public long getAndIncrement(T obj) {
  • long prev, next;
  • do {
  • prev = get(obj);
  • next = prev + 1;
  • } while (!compareAndSet(obj, prev, next));
  • return prev;
  • }
  • // 以原子方式将此更新器管理的给定对象字段当前值减1
  • public long getAndDecrement(T obj) {
  • long prev, next;
  • do {
  • prev = get(obj);
  • next = prev - 1;
  • } while (!compareAndSet(obj, prev, next));
  • return prev;
  • }
  • // 以原子方式将给定值添加到此更新器管理的给定对象的字段的当前值
  • public long getAndAdd(T obj, long delta) {
  • long prev, next;
  • do {
  • prev = get(obj);
  • next = prev + delta;
  • } while (!compareAndSet(obj, prev, next));
  • return prev;
  • }
  • // 以原子方式将此更新器管理的给定对象字段当前值加1
  • public long incrementAndGet(T obj) {
  • long prev, next;
  • do {
  • prev = get(obj);
  • next = prev + 1;
  • } while (!compareAndSet(obj, prev, next));
  • return next;
  • }
  • // 以原子方式将此更新器管理的给定对象字段当前值减1
  • public long decrementAndGet(T obj) {
  • long prev, next;
  • do {
  • prev = get(obj);
  • next = prev - 1;
  • } while (!compareAndSet(obj, prev, next));
  • return next;
  • }
  • // 以原子方式将给定值添加到此更新器管理的给定对象的字段的当前值
  • public long addAndGet(T obj, long delta) {
  • long prev, next;
  • do {
  • prev = get(obj);
  • next = prev + delta;
  • } while (!compareAndSet(obj, prev, next));
  • return next;
  • }
  • // 以原子方式使用给定的方法获取的值更新当前的值,并返回旧值,自JDK1.8起提供。LongUnaryOperator会被多次调用
  • public final long getAndUpdate(T obj, LongUnaryOperator updateFunction) {
  • long prev, next;
  • do {
  • prev = get(obj);
  • next = updateFunction.applyAsLong(prev);
  • } while (!compareAndSet(obj, prev, next));
  • return prev;
  • }
  • // 以原子方式使用给定的方法获取的值更新当前的值,并返回新值,自JDK1.8起提供。LongUnaryOperator会被多次调用
  • public final long updateAndGet(T obj, LongUnaryOperator updateFunction) {
  • long prev, next;
  • do {
  • prev = get(obj);
  • next = updateFunction.applyAsLong(prev);
  • } while (!compareAndSet(obj, prev, next));
  • return next;
  • }
  • // 以原子方式使用给定的方法获取的值将x作为参数更新当前的值,并返回旧值,自JDK1.8起提供。LongUnaryOperator会被多次调用
  • public final long getAndAccumulate(T obj, long x,
  • LongBinaryOperator accumulatorFunction) {
  • long prev, next;
  • do {
  • prev = get(obj);
  • next = accumulatorFunction.applyAsLong(prev, x);
  • } while (!compareAndSet(obj, prev, next));
  • return prev;
  • }
  • // 以原子方式使用给定的方法获取的值将x作为参数更新当前的值,并返回旧值,自JDK1.8起提供。LongUnaryOperator会被多次调用
  • public final long accumulateAndGet(T obj, long x,
  • LongBinaryOperator accumulatorFunction) {
  • long prev, next;
  • do {
  • prev = get(obj);
  • next = accumulatorFunction.applyAsLong(prev, x);
  • } while (!compareAndSet(obj, prev, next));
  • return next;
  • }
  • // CAS原子更新器
  • private static final class CASUpdater<T> extends java.util.concurrent.atomic.AtomicLongFieldUpdater<T> {
  • private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
  • private final long offset;
  • /**
  • * if field is protected, the subclass constructing updater, else
  • * the same as tclass
  • */
  • private final Class<?> cclass;
  • /**
  • * class holding the field
  • */
  • private final Class<T> tclass;
  • CASUpdater(final Class<T> tclass, final String fieldName,
  • final Class<?> caller) {
  • final Field field;
  • final int modifiers;
  • try {
  • // 禁止对字段的安全检查
  • field = AccessController.doPrivileged(
  • new PrivilegedExceptionAction<Field>() {
  • public Field run() throws NoSuchFieldException {
  • return tclass.getDeclaredField(fieldName);
  • }
  • });
  • // 获取字段的修饰符
  • modifiers = field.getModifiers();
  • // 检查访问权限
  • sun.reflect.misc.ReflectUtil.ensureMemberAccess(
  • caller, tclass, null, modifiers);
  • ClassLoader cl = tclass.getClassLoader();
  • ClassLoader ccl = caller.getClassLoader();
  • if ((ccl != null) && (ccl != cl) &&
  • ((cl == null) || !isAncestor(cl, ccl))) {
  • sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
  • }
  • } catch (PrivilegedActionException pae) {
  • throw new RuntimeException(pae.getException());
  • } catch (Exception ex) {
  • throw new RuntimeException(ex);
  • }
  • // 检查字段类型是否为long
  • if (field.getType() != long.class)
  • throw new IllegalArgumentException("Must be long type");
  • // 检查是否被volatile修饰
  • if (!Modifier.isVolatile(modifiers))
  • throw new IllegalArgumentException("Must be volatile type");
  • // Access to protected field members is restricted to receivers only
  • // of the accessing class, or one of its subclasses, and the
  • // accessing class must in turn be a subclass (or package sibling)
  • // of the protected member's defining class.
  • // If the updater refers to a protected field of a declaring class
  • // outside the current package, the receiver argument will be
  • // narrowed to the type of the accessing class.
  • this.cclass = (Modifier.isProtected(modifiers) &&
  • tclass.isAssignableFrom(caller) &&
  • !isSamePackage(tclass, caller))
  • ? caller : tclass;
  • this.tclass = tclass;
  • this.offset = U.objectFieldOffset(field);
  • }
  • /**
  • * Checks that target argument is instance of cclass. On
  • * failure, throws cause.
  • */
  • private final void accessCheck(T obj) {
  • if (!cclass.isInstance(obj))
  • throwAccessCheckException(obj);
  • }
  • /**
  • * Throws access exception if accessCheck failed due to
  • * protected access, else ClassCastException.
  • */
  • private final void throwAccessCheckException(T obj) {
  • if (cclass == tclass)
  • throw new ClassCastException();
  • else
  • throw new RuntimeException(
  • new IllegalAccessException(
  • "Class " +
  • cclass.getName() +
  • " can not access a protected member of class " +
  • tclass.getName() +
  • " using an instance of " +
  • obj.getClass().getName()));
  • }
  • public final boolean compareAndSet(T obj, long expect, long update) {
  • accessCheck(obj);
  • return U.compareAndSwapLong(obj, offset, expect, update);
  • }
  • public final boolean weakCompareAndSet(T obj, long expect, long update) {
  • accessCheck(obj);
  • return U.compareAndSwapLong(obj, offset, expect, update);
  • }
  • public final void set(T obj, long newValue) {
  • accessCheck(obj);
  • U.putLongVolatile(obj, offset, newValue);
  • }
  • public final void lazySet(T obj, long newValue) {
  • accessCheck(obj);
  • U.putOrderedLong(obj, offset, newValue);
  • }
  • public final long get(T obj) {
  • accessCheck(obj);
  • return U.getLongVolatile(obj, offset);
  • }
  • public final long getAndSet(T obj, long newValue) {
  • accessCheck(obj);
  • return U.getAndSetLong(obj, offset, newValue);
  • }
  • public final long getAndAdd(T obj, long delta) {
  • accessCheck(obj);
  • return U.getAndAddLong(obj, offset, delta);
  • }
  • public final long getAndIncrement(T obj) {
  • return getAndAdd(obj, 1);
  • }
  • public final long getAndDecrement(T obj) {
  • return getAndAdd(obj, -1);
  • }
  • public final long incrementAndGet(T obj) {
  • return getAndAdd(obj, 1) + 1;
  • }
  • public final long decrementAndGet(T obj) {
  • return getAndAdd(obj, -1) - 1;
  • }
  • public final long addAndGet(T obj, long delta) {
  • return getAndAdd(obj, delta) + delta;
  • }
  • }
  • private static final class LockedUpdater<T> extends java.util.concurrent.atomic.AtomicLongFieldUpdater<T> {
  • private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
  • private final long offset;
  • /**
  • * if field is protected, the subclass constructing updater, else
  • * the same as tclass
  • */
  • private final Class<?> cclass;
  • /**
  • * class holding the field
  • */
  • private final Class<T> tclass;
  • LockedUpdater(final Class<T> tclass, final String fieldName,
  • final Class<?> caller) {
  • Field field = null;
  • int modifiers = 0;
  • try {
  • field = AccessController.doPrivileged(
  • new PrivilegedExceptionAction<Field>() {
  • public Field run() throws NoSuchFieldException {
  • return tclass.getDeclaredField(fieldName);
  • }
  • });
  • modifiers = field.getModifiers();
  • sun.reflect.misc.ReflectUtil.ensureMemberAccess(
  • caller, tclass, null, modifiers);
  • ClassLoader cl = tclass.getClassLoader();
  • ClassLoader ccl = caller.getClassLoader();
  • if ((ccl != null) && (ccl != cl) &&
  • ((cl == null) || !isAncestor(cl, ccl))) {
  • sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
  • }
  • } catch (PrivilegedActionException pae) {
  • throw new RuntimeException(pae.getException());
  • } catch (Exception ex) {
  • throw new RuntimeException(ex);
  • }
  • if (field.getType() != long.class)
  • throw new IllegalArgumentException("Must be long type");
  • if (!Modifier.isVolatile(modifiers))
  • throw new IllegalArgumentException("Must be volatile type");
  • // Access to protected field members is restricted to receivers only
  • // of the accessing class, or one of its subclasses, and the
  • // accessing class must in turn be a subclass (or package sibling)
  • // of the protected member's defining class.
  • // If the updater refers to a protected field of a declaring class
  • // outside the current package, the receiver argument will be
  • // narrowed to the type of the accessing class.
  • this.cclass = (Modifier.isProtected(modifiers) &&
  • tclass.isAssignableFrom(caller) &&
  • !isSamePackage(tclass, caller))
  • ? caller : tclass;
  • this.tclass = tclass;
  • this.offset = U.objectFieldOffset(field);
  • }
  • /**
  • * Checks that target argument is instance of cclass. On
  • * failure, throws cause.
  • */
  • private final void accessCheck(T obj) {
  • if (!cclass.isInstance(obj))
  • throw accessCheckException(obj);
  • }
  • /**
  • * Returns access exception if accessCheck failed due to
  • * protected access, else ClassCastException.
  • */
  • private final RuntimeException accessCheckException(T obj) {
  • if (cclass == tclass)
  • return new ClassCastException();
  • else
  • return new RuntimeException(
  • new IllegalAccessException(
  • "Class " +
  • cclass.getName() +
  • " can not access a protected member of class " +
  • tclass.getName() +
  • " using an instance of " +
  • obj.getClass().getName()));
  • }
  • public final boolean compareAndSet(T obj, long expect, long update) {
  • accessCheck(obj);
  • synchronized (this) {
  • long v = U.getLong(obj, offset);
  • if (v != expect)
  • return false;
  • U.putLong(obj, offset, update);
  • return true;
  • }
  • }
  • public final boolean weakCompareAndSet(T obj, long expect, long update) {
  • return compareAndSet(obj, expect, update);
  • }
  • public final void set(T obj, long newValue) {
  • accessCheck(obj);
  • synchronized (this) {
  • U.putLong(obj, offset, newValue);
  • }
  • }
  • public final void lazySet(T obj, long newValue) {
  • set(obj, newValue);
  • }
  • public final long get(T obj) {
  • accessCheck(obj);
  • synchronized (this) {
  • return U.getLong(obj, offset);
  • }
  • }
  • }
  • // 判断ClassLoader继承性
  • static boolean isAncestor(ClassLoader first, ClassLoader second) {
  • ClassLoader acl = first;
  • do {
  • acl = acl.getParent();
  • if (second == acl) {
  • return true;
  • }
  • } while (acl != null);
  • return false;
  • }
  • // 判断两个类是否在同一个包内
  • private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
  • return class1.getClassLoader() == class2.getClassLoader()
  • && Objects.equals(getPackageName(class1), getPackageName(class2));
  • }
  • // 获取包名
  • private static String getPackageName(Class<?> cls) {
  • String cn = cls.getName();
  • int dot = cn.lastIndexOf('.');
  • return (dot != -1) ? cn.substring(0, dot) : "";
  • }
  • }

AtomicLongFieldUpdater是一个抽象类,在使用它的时候,需要通过它的静态方法newUpdater(Class<U>, String)传入需要访问的类和更新的字段名,AtomicLongFieldUpdater会根据虚拟机实现情况返回CASUpdater或LockedUpdater实例。

CASUpdater或LockedUpdater都是位于AtomicLongFieldUpdater中继承自AtomicLongFieldUpdater的静态内部类,这两个类的实现区别在于:在做各类更新操作的时候,CASUpdater使用的是CAS方式,而LockedUpdater使用的是粗暴的synchronized加锁方式。

具体代码都比较简单,这里不做详解。下面将给出一个AtomicLongFieldUpdater的简单示例。

3. AtomicLongFieldUpdater示例

  • class Number {
  • public volatile long value;
  • }
  • public class AtomicLongFieldUpdaterTest {
  • public static void main(String[] args) {
  • AtomicLongFieldUpdater<Number> value = AtomicLongFieldUpdater.newUpdater(Number.class, "value");
  • Number number = new Number();
  • // 设置number对象的value字段值为1000
  • value.set(number, 1000);
  • // 获取number对象的value字段值
  • System.out.println(value.get(number));
  • // 对number对象的value加1,获取加1后的值
  • System.out.println(value.incrementAndGet(number));
  • }
  • }

运行结果如下:

  • 1000
  • 1001