美文网首页
Java AtomicReferenceFieldUpdater

Java AtomicReferenceFieldUpdater

作者: 南风nanfeng | 来源:发表于2020-01-03 11:51 被阅读0次

    AtomicReferenceFieldUpdater出自java并发框架大神Doug Lea之手,这位哥基本承java.util.concurrent包的开发,让人佩服。本文来自查阅源码及注释的理解。
    另外JUC提供3个原子更新器:

    • 1.AtomicIntegerFieldUpdater
    • 2.AtomicLongFieldUpdater
    • 3.AtomicReferenceFieldUpdater

    仔细看过源码可以发现,AtomicInteger 和 AtomicIntegerFieldUpdater 的公共 API 几乎一模一样,所以在提供 CAS 操作这个层面,两者是几乎等价的。

    该类用途

     * A reflection-based utility that enables atomic updates to
     * designated {@code volatile} reference fields of designated classes.  
    

    简单来说,AtomicReferenceFieldUpdater能原子更新类中被volatile修饰的变量。
    原理是通过反射实现对字段的原子更新。
    那么问题来了,由于反射的性能较低,为什么不直接用 AtomicInteger,而要用 volatile + AtomicIntegerFieldUpdater 呢?
    注释的解释是:

    This class is designed for use in atomic data structures  
    in which several reference fields of the same node are  
    independently subject to atomic updates. 
    

    这个类可以对多个属性原子更新,实际上AtomicInteger也支持。
    当然 AtomicXFieldUpdater 并非毫无用处,相对原子类而言,有如下优点:

    • 1、AtomicX 毕竟是复杂类型,空间占用比 volatile 的原始类型要大,在超大数量的场景下,AtomicXFieldUpdater 在内存占用方面有优势;
    • 2、如果某个字段的 所有操作 都是原子操作,那可以用 AtomicX,但有的场景下,字段既需要原子操作,- - - 3、需要普通操作,这时可以考虑用 AtomicXFieldUpdater;
    • 4、如果要原子更新的字段在第三方类中,无法直接修改源码,则使用 AtomicXFieldUpdater;

    实例化

        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,表示外部包的类无法创建,正确姿势:调用静态方法newUpdater创建。

    • 第一个参数tclass表示引用类,持有属性的类。
    • 第二个参数vclass表示属性的类型。
    • 第三个参数fieldName表示属性的名称,能在类反射中找个这个属性。

    案例

    public class Node {
        private volatile Node left;
        private volatile Node right;
    
        private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
                AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
    
        private static final AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
                AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
    
        public Node getLeft() {
            return left;
        }
    
        public boolean compareAndSetLeft(Node expect, Node update) {
            return leftUpdater.compareAndSet(this, expect, update);
        }
    }
    

    缺陷

     * <p>Note that the guarantees of the {@code compareAndSet}
     * method in this class are weaker than in other atomic classes.
     * Because this class cannot ensure that all uses of the field
     * are appropriate for purposes of atomic access, it can
     * guarantee atomicity only with respect to other invocations of
     * {@code compareAndSet} and {@code set} on the same updater.
    

    即原子更新器的 CAS 比对应的原子类弱,只能保证通过 同一 updater 实例 对字段的更新是原子的,以下场景下无法保证原子性:

    • 1、同时使用多个 updater;
    • 2、除 updater 外,还使用(无并发处理的)普通更新操作;

    相关文章

      网友评论

          本文标题:Java AtomicReferenceFieldUpdater

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