美文网首页工作生活
J.U.C之Atomic:属性类型的原子类

J.U.C之Atomic:属性类型的原子类

作者: 贪睡的企鹅 | 来源:发表于2019-07-04 14:49 被阅读0次

属性类型的原子类

类名 说明
AtomicIntegerFieldUpdater 原子更新整型的字段的更新器。
AtomicLongFieldUpdater 原子更新长整型字段的更新器。
AtomicReferenceFieldUpdater 原子更新引用类型字段的更新器。

AtomicReferenceFieldUpdater

AtomicReferenceFieldUpdater用来表示类中引用类型属性字段原子操作类.

操作限制

  • 字段必须是volatile类型的,在线程之间共享变量时保证立即可见

  • 字段的描述类型(修饰符public/protected/default/private)是与调用者与操作对象字段的关系一致

  • 只能是实例变量,不能是类变量

  • 只能是可修改变量,不能使final变量,因为final的语义就是不可修改

原理解析

AtomicReferenceFieldUpdater本质上使用Unsafe 对象属性相关API函数。
我们需要传入操作对象obj,原始值,预期值,和当前值。

U.compareAndSwapObject(obj, offset, expect, update);

而AtomicReferenceFieldUpdater为了描述一个类的属性操作,我们需要知道类的Class,属性的Class,以及当前操作的属性的修饰符(是否有权限)。

 /**
         * 属性在内存中的偏移地址
         */
        private final long offset;

        /**
         * 操作类Class
         */
        private final Class<?> cclass;

        private final Class<T> tclass;

        /**
         * 操作类属性Class
         */
        private final Class<V> vclass;

当我们创建一个AtomicReferenceFieldUpdater只需要传入表示该字段所在的类的Class,字段类型的Class,以及操作属性的名称(内部会使用反射获取字段的标识符)

/**
     * 获取一个AtomicReferenceFieldUpdater实例(用来表示类中的一个属性字段)
     * @param tclass  表示该字段所在的类
     * @param vclass  表示该字段的类型
     * @param fieldName  表示要更新的字段名
     */
    @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());
    }
    
    AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
                                        final Class<V> vclass,
                                        final String fieldName,
                                        final Class<?> caller) {

            /** 操作类属性Field **/
            final Field field;
            /** 操作类属性的class **/
            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");

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

有了这些我们就可以使用CAS对类的属性操作了。

 /**
         * 使用CAS设置对象属性的值
         */
        public final boolean compareAndSet(T obj, V expect, V update) {
            accessCheck(obj);
            valueCheck(update);
            return U.compareAndSwapObject(obj, offset, expect, update);
        }

        /**
         * 使用CAS设置对象属性的值
         */
        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);
        }

        /**
         * 使用原子的方式设置对象属性的值(CAS+循环),并返回旧值
         */
        @SuppressWarnings("unchecked")
        public final V getAndSet(T obj, V newValue) {
            accessCheck(obj);
            valueCheck(newValue);
            return (V)U.getAndSetObject(obj, offset, newValue);
        }

相关文章

网友评论

    本文标题:J.U.C之Atomic:属性类型的原子类

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