RxJava SerializedObserver实现

时间:2016-09-27 17:12:43

标签: java concurrency rx-java

在阅读David Karnok关于RxJava内部的this文章时,我遇到了一个实现与RxJava SerializedObserver类相近的事情的例子。这是代码:

class ValueListEmitterLoop<T> {
    List<T> queue;                           
    boolean emitting;
    Consumer<? super T> consumer;

    public void emit(T value) {
        synchronized (this) {
            if (emitting) {
                List<T> q = queue;
                if (q == null) {
                    q = new ArrayList<>();   
                    queue = q;
                }
                q.add(value);
                return;
            }
            emitting = true;
        }
        consumer.accept(value);              
        for (;;) {
             List<T> q;
             synchronized (this) {           
                 q = queue;
                 if (q == null) {            
                     emitting = false;
                     return;
                 }
                 queue = null;               
             }
             q.forEach(consumer);            
        }        
    }
}

所以问题是为什么在第一个q块中引入了内部变量synchronized?我在第二个synchronized块中清楚地看到了它背后的原因。是否有任何原因导致我不能使用:

if (queue == null) {
    queue = new ArrayList<>();
}
queue.add(value);

1 个答案:

答案 0 :(得分:2)

我觉得将字段读入局部变量是一个好习惯,特别是如果它们被多次使用并且附近有一些易失/同步访问。

例如,以下是一种常见模式:

volatile boolean cancelled;

final Queue<T> queue;

final Subscriber<? super T> actual;

void drain() {
    Subscriber<? super T> a = actual;
    Queue<T> q = queue;

    for (;;) {
        if (cancelled) {
            return;
        }

        T v = q.poll();

        if (v == null) {
             a.onComplete();
             return;
        }

        a.onNext(v);
    }
}

如果aq是字段访问,则处理器/ JVM必须始终从内存中读取它们,因为cancelled和内部类似的原子的易失性访问poll()