繁体   English   中英

蓄电池是否是线程安全的?

[英]Are accumulators thread-safe?

我正在使用累加器,并想知道这些对象是否是线程安全的?

accumInt是一种AccumulatorParam<Integer>

// Current value accumInt -> 6
AccumulatorThread t1 = new AccumulatorThread();
t1.setAccum(accumInt); 
t1.setValueToAdd(5);

AccumulatorThread t2 = new AccumulatorThread();
t2.setAccum(accumInt);
t2.setValueToAdd(7);

new Thread(t1).start();
new Thread(t2).start();

System.out.println(accumInt.value()); // 11 or 13 or 18

AccumlatorThread类:

class AccumulatorThread implements Runnable {
    Accumulator<Integer> accum;
    Integer              valueToAdd;

    public Integer getValueToAdd() {
        return valueToAdd;
    }


    public void setValueToAdd(Integer valueToAdd) {
        this.valueToAdd = valueToAdd;
    }

    public Accumulator<Integer> getAccum() {
        return accum;
    }


    public void setAccum(Accumulator<Integer> accum) {
        this.accum = accum;
    }

    public void run() {
        System.out.println("Value to Add in Thread : "+valueToAdd);
        accum.add(valueToAdd);
    }
}

该行为表明它不是线程安全的。 我错过了什么吗?

OOC为什么要在同一个程序中设置和读取累加器? 累加器通常由工作线程添加,并且只能由驱动程序线程读取。

Worker1:   accumulator.add(increment)
Worker2:   accumulator.add(someOtherIncrement)

Driver:  println(accumulator.value)

现在,您要询问mulithreading在驱动程序的不同线程中设置/读取值。 为了什么目的? 在这种情况下,只需使用本地JVM AtomicIntegerAtomicLong

累加器是仅通过关联操作“添加”的变量,因此可以并行有效地支持。

累加器不是线程安全的。 只有SparkContext可以在多个线程中使用。

扩展@javadba@zsxwing的另外两个很棒的答案。

我对Apache Spark的理解是它们可能是也可能不是线程安全的。 这其实并不重要。 由于驱动程序“远离”其工作者(它们通常通过网络或至少在JVM之间相互通信 - 除非它是本地模式)所有对累加器的更新都会到达逐个处理的消息,从而确保单线程更新到累加器。

累加器不是线程安全的,实际上它们不需要是线程安全的。 对于执行程序,累加器是只写变量,它们可以由执行程序添加,并且可以由驱动程序读取。 驱动程序使用DAGScheduler.updateAccumulators方法在任务完成后更新累加器的值,并且仅从运行调度循环的线程调用此方法。 一次只处理一个任务完成事件。 这就是为什么不需要累加器是线程安全的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM