1. 程式人生 > >AtomicReferenceFieldUpdater原始碼閱讀筆記

AtomicReferenceFieldUpdater原始碼閱讀筆記

AtomicReferenceFieldUpdater使用

 AtomicReferenceFieldUpdater的作用就是原子更新類中被volatile修飾的欄位,具體使用如下:

class Person {
    volatile String name = "lx";
}
public class ReferenceFieldUpdaterTest {

    public static void main(String[] args) {
        AtomicReferenceFieldUpdater updater = AtomicReferenceFieldUpdater.newUpdater(Person.class, String.class, "name"
); Person person = new Person(); updater.compareAndSet(person, person.name, "Kylin"); System.out.println("------->" + person.name); } }

輸出結果如下:

------->Kylin

AtomicReferenceFieldUpdater原始碼分析

 AtomicReferenceFieldUpdater定義了一組抽象方法和工廠構造器如下:

//定義工廠方法,構建AtomicReferenceFieldUpdater
public static <U,W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) { return new AtomicReferenceFieldUpdaterImpl<U,W> (tclass, vclass, fieldName, Reflection.getCallerClass()); } //預設構造方法
protected AtomicReferenceFieldUpdater() {} //cas更新指定欄位 public abstract boolean compareAndSet(T obj, V expect, V update); public abstract boolean weakCompareAndSet(T obj, V expect, V update); public abstract void set(T obj, V newValue); public abstract void lazySet(T obj, V newValue); public abstract V get(T obj); public V getAndSet(T obj, V newValue) { V prev; do { prev = get(obj); } while (!compareAndSet(obj, prev, newValue)); return prev; } public final V getAndUpdate(T obj, UnaryOperator<V> updateFunction) { V prev, next; do { prev = get(obj); next = updateFunction.apply(prev); } while (!compareAndSet(obj, prev, next)); return prev; } public final V updateAndGet(T obj, UnaryOperator<V> updateFunction) { V prev, next; do { prev = get(obj); next = updateFunction.apply(prev); } while (!compareAndSet(obj, prev, next)); return next; } public final V getAndAccumulate(T obj, V x, BinaryOperator<V> accumulatorFunction) { V prev, next; do { prev = get(obj); next = accumulatorFunction.apply(prev, x); } while (!compareAndSet(obj, prev, next)); return prev; } public final V accumulateAndGet(T obj, V x, BinaryOperator<V> accumulatorFunction) { V prev, next; do { prev = get(obj); next = accumulatorFunction.apply(prev, x); } while (!compareAndSet(obj, prev, next)); return next; }

 內部類實現如下,程式碼整體較簡單,注重看下構造器中的一個小細節,Class被ClassLoader載入,所有的ClassLoader應該在一個雙親委託模型的ClassLoader載入鏈中。tclass和vclass的類載入器會判斷是否在一個類載入器鏈中。

 private static final class AtomicReferenceFieldUpdaterImpl<T,V>
        extends AtomicReferenceFieldUpdater<T,V> {
        //使用Unsafe做CAS操作
        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
        private final long offset;
        /**
         * 待更新的的物件的類的Class物件
         */
        private final Class<?> cclass;
        /** 待操作的目標物件 */
        private final Class<T> tclass;
        /** 待操作的欄位的型別 */
        private final Class<V> vclass;


        /** 建立原子更新器 */
        AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
                                        final Class<V> vclass,
                                        final String fieldName,
                                        final Class<?> caller) {
            final Field field;
            final Class<?> fieldClass;
            final int modifiers;
            try {
            //獲取tclass的Field
                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();
                //判斷class和修改的欄位的類載入器是否在一個類載入器委託鏈中
                if ((ccl != null) && (ccl != cl) &&
                    ((cl == null) || !isAncestor(cl, ccl))) {
                    sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
                }
                fieldClass = field.getType();
            } catch (PrivilegedActionException pae) {
                throw new RuntimeException(pae.getException());
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }

            if (vclass != fieldClass)
                throw new ClassCastException();
            if (vclass.isPrimitive())
                throw new IllegalArgumentException("Must be reference type");

            if (!Modifier.isVolatile(modifiers))
                throw new IllegalArgumentException("Must be volatile type");

            this.cclass = (Modifier.isProtected(modifiers) &&
                           tclass.isAssignableFrom(caller) &&
                           !isSamePackage(tclass, caller))
                          ? caller : tclass;
            this.tclass = tclass;
            this.vclass = vclass;
            this.offset = U.objectFieldOffset(field);
        }


         //判斷第二個類載入器是否能在第一個載入器委託鏈中找到
        private static boolean isAncestor(ClassLoader first, ClassLoader second) {
            ClassLoader acl = first;
            do {
                acl = acl.getParent();
                if (second == acl) {
                    return true;
                }
            } while (acl != null);
            return false;
        }


         //判斷兩個classes是否是相同的類載入器和包修飾
        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) : "";
        }

        //判斷目標引數是否obj的例項
        private final void accessCheck(T obj) {
            if (!cclass.isInstance(obj))
                throwAccessCheckException(obj);
        }


        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()));
        }

        private final void valueCheck(V v) {
            if (v != null && !(vclass.isInstance(v)))
                throwCCE();
        }

        static void throwCCE() {
            throw new ClassCastException();
        }

        //原子更新
        public final boolean compareAndSet(T obj, V expect, V update) {
            accessCheck(obj);
            valueCheck(update);
            return U.compareAndSwapObject(obj, offset, expect, update);
        }

        public final boolean weakCompareAndSet(T obj, V expect, V update) {
            // same implementation as strong form for now
            accessCheck(obj);
            valueCheck(update);
            return U.compareAndSwapObject(obj, offset, expect, update);
        }

        public final void set(T obj, V newValue) {
            accessCheck(obj);
            valueCheck(newValue);
            U.putObjectVolatile(obj, offset, newValue);
        }

        public final void lazySet(T obj, V newValue) {
            accessCheck(obj);
            valueCheck(newValue);
            U.putOrderedObject(obj, offset, newValue);
        }

        @SuppressWarnings("unchecked")
        public final V get(T obj) {
            accessCheck(obj);
            return (V)U.getObjectVolatile(obj, offset);
        }

        @SuppressWarnings("unchecked")
        public final V getAndSet(T obj, V newValue) {
            accessCheck(obj);
            valueCheck(newValue);
            return (V)U.getAndSetObject(obj, offset, newValue);
        }
    }