并发写入数组时的可见性问题

时间:2016-05-25 17:17:35

标签: java concurrency visibility

在Java中,如果多个线程异步写入基本(双)数组的各个部分,并且(仅)主线程在所有线程完成写入后从数组中读取。

  1. 是否存在可见性问题,即有可能读取或写入原始数组的线程本地版本?
  2. 如果1.为真,这是通过在读取主线程之​​前添加内存屏障来解决的吗?你建议使用哪一个?
  3. 以下示例代码。

    非常感谢, 曼努埃尔

        //Example code to calculate distance of 1 point to 1mln other points:
        double[][] history = this.createRandomMatrix(1000000,8);
        double[] order = this.createRandomMatrix(1,8)[0];
        double[] result = new double[1000000];
        for(int i = 0; i< 100;i++){
            pool.execute(new Calculator(history, newPoint, result,i*10000,10000    + i * 10000));
        }
        pool.shutdown();
        try {
            pool.awaitTermination(1, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //read happens here
    
        //Calculator run function
        public void run() {
            for(int i = start;i<end;i++){
                result[i] = this.computeDistance(history[i],order);
            }
        }
    

2 个答案:

答案 0 :(得分:1)

由于它是一个你正在讨论的数组(静态数组),除非intentionally created,否则不会创建线程本地版本。每个块将读/写同一存储块(阵列的存储块)中的地址。由于写入是对阵列的单独部分进行的,因此不会发生data races。由于您说在完成其他线程的写入后由主线程完成读取,因此不需要同步。

答案 1 :(得分:0)

存在可见性问题。这并不意味着每个线程都有它的本地副本。它只是意味着不能保证主线程可以看到其他线程写的值。

我没有试图设置内存障碍(我无法提出同步所有对result数组的访问背后的任何想法,这可能会破坏多个线程的整个目的),我建议提交Callable你的遗嘱执行人:

List<Future> futures = ExecutorService#invokeAll(java.util.Collection<? extends java.util.concurrent.Callable<T>>)

然后每个线程都可以返回自己的结果,主线程将使用它们并获得最终结果。无需共享状态result

相关问题