美文网首页
java.util.concurrent.atomic源码学习(

java.util.concurrent.atomic源码学习(

作者: 果拉图 | 来源:发表于2019-08-16 11:19 被阅读0次

    1 上节回顾

    我们在java.util.concurrent.atomic源码学习(一)https://www.jianshu.com/p/d865264818af中介绍了原子类,原子数组,以及带计数器的原子类,下面我们将介绍对于非原子变量,我们如何实现原子操作,主要是看AtomicXXXFieldUpdater的源代码,下面以AtomicReferenceFieldUpdater为例进行分析。

    2 AtomicReferenceFieldUpdater源代码阅读

    我们在上一节了解到想要进行对变量进行原子操作,unsafe方法入参需要类对象,以及修改field的内存偏移位置,类对象比较好传,难得的是如何获取待修改field的内存偏移位置,在AtomicReferenceFieldUpdater中是通过反射获取待修改field的内存偏移位置的,代码如下

    /**
    ** 首先是构造器,构造器new了一个实现类,
    ** Reflection.getCallerClass()从名字上来看是获取调用类的信息,
    ** 主要用途是类安全,判断Caller类有没有修改filed的权限
    **/
    @CallerSensitive
    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());
    }
    
    /**
    ** getAndUpdate方法都差不多,只是入参多了一个obj
    ** @param obj An object whose field to get and set
    ** 这个obj是持有需要更新的filed的原始对象
    **/
    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;
    }
    

    下面我们揭开AtomicReferenceFieldUpdaterImpl的神秘面纱

    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 {
            //通过反射获取待更新对象的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();
             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");
         //检查是否是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.vclass = vclass;
         this.offset = U.objectFieldOffset(field);
     }
    

    代码虽然很多,但核心思想却比较简单,获取并判断field是否可以进行更新,主要检查了访问权限,检查了filed的类型,检查了field是否是volatile类型。最后的目的是为了拿到这个field的offset偏移值,拿到offset后,后面的更新也就水到渠成了,值得注意的是由于采用了反射,可能存在类型不一致的问题,因此做了一些check。

    public final boolean compareAndSet(T obj, V expect, V update) {
        accessCheck(obj);
        valueCheck(update);
        return U.compareAndSwapObject(obj, offset, expect, update);
    }
    
    private final void accessCheck(T obj) {
        if (!cclass.isInstance(obj))
            throwAccessCheckException(obj);
    }
    
    private final void valueCheck(V v) {
        if (v != null && !(vclass.isInstance(v)))
            throwCCE();
    }
    
    public final V getAndSet(T obj, V newValue) {
        accessCheck(obj);
        valueCheck(newValue);
        return (V)U.getAndSetObject(obj, offset, newValue);
    }
    

    相关文章

      网友评论

          本文标题:java.util.concurrent.atomic源码学习(

          本文链接:https://www.haomeiwen.com/subject/kolfsctx.html