美文网首页
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