【问题标题】:How to access arrays from multi-thread?如何从多线程访问数组?
【发布时间】:2013-07-21 22:06:40
【问题描述】:

简单来说,我的问题如下:

我有一个名为Test的类,它有3个双数组,分别命名为array1、array2、array3(假设它们的长度相同)。它有一个名为Estep的主要函数,我需要用multi-来实现这个函数线程以提高速度。

在Estep中,我需要修改array1和array2,array3仅供读取。我定义了一个名为which_array的指示变量来指示要修改哪个数组。我将三个数组传递给Estep和修改array1和array2。

我的代码如下,我测试了一下,效果很好,Estep中array1和array2的修改可以在Test类中看到。但我仍然怀疑它是否绝对正确。我想知道是否应该将 volatile 添加到 Test 类中的三个 array1 中,还是需要一些同步机制?

任何建议将不胜感激!

public class Test{

    double[] array1;
    double[] array2;
    double[] array3;
    //for simplifization, I omitted the code for allocation and initialization of the the arrays.
    public void EstepInTest()
    {
        final CountDownLatch countdown = new CountDownLatch(2);

    Estep modifyArray1 = new Estep(array1, array2, array3, 1,countdown);
    Thread t1 = new Thread( firstHalf);
    t1.start();

    Estep modifyArray2 = new Estep(array1, array2, array3, 2,countdown);    
        Thread t2 = new Thread(secondHalf);
    t2.start();

    try{
    countdown.await();
    }catch (InterruptedException e) {
        e.printStackTrace();
    }

        //do next things
    }

}

class Estep implements Runnable{

    double[] array1;
    double[] array2;
    double[] array3;
    int which_array;

    Estep(double[] array1, double[] array2, double[] array3, int which_array, CountDownLatch cd)
    {
        this.array1 = array1;
        this.array2 = array2;
        this.array3 = array3;
        this.which_array = which_array;
        this.cd = cd;
    }

    public void run(){

        if( this.which_array == 1){
           for( int i = 0; i < array1.length; ++i )
           {   
               array1[i] = array1[i] + array3[i];
           }  
        }else{
           for( int i = 0; i < array2.length; ++i )
           {   
               array2[i] = array2[i] + array3[i];
           }
        }
        cd.countDown();
   }

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    没错。 CountDownLatch.await() 保证在它返回之前完成的一切happens-before在它返回之后完成的一切。

    如果您只是将要修改的数组传递给 Estep 构造函数,而不是传递两个数组和一个幻数来指示要修改哪一个,那么您的代码会更简洁。

    编辑:

    关于对array3 的访问,它也是安全的,因为正如the documentation of the concurrent package 中所解释的,在线程上调用start在启动线程中的任何操作之前发生 .因此,这两个线程将看到在启动它们之前对array3 所做的所有修改。

    另外,请注意,使数组易失性只会使数组引用易失性。它不会使其元素易变。

    【讨论】:

    • 感谢您的帮助。我的代码只是为了演示,因为对每个数组的修改逻辑不同,所以我传递了两个数组和一个幻数。为了验证,我不需要将 volatile 添加到 array3 和另外两个数组,因为两个线程同时访问 array3。由于我对java中多线程的理解非常有限,所以如果我问一个愚蠢的问题,请不要介意,谢谢
    【解决方案2】:

    考虑只向 Estep 传递两个数组,一个用于修改,一个用于读取。在这种情况下,您不需要多余的 which-array 变量和运行中的通用代码

    【讨论】:

      【解决方案3】:

      我对倒计时锁不太熟悉。

      您还可以同步数组对象本身。您可以通过将数组设置为要在 getter 和 setter 中同步的监视器对象来做到这一点。这应该可以防止对影响当前行的数组进行任何访问,并且会阻止以异步方式发生的最少代码量。

      // In the original test class
      public int getArray1(int index) {
      
         unsynchronized_statements...
      
         int result;
         synchronized(array1) {
             result = array1[index]...
         }
         return result;
      }
      

      【讨论】:

      • 感谢您的建议,因为我使用两个线程分别修改两个数组,所以保证只有一个线程同时修改特定数组,所以不需要同步我的问题设置中的数组?
      • 好的,我想在这种情况下你应该没问题,因为 await 方法应该阻止主类使用数组,直到你准备好。我习惯于在非等待上下文中设置后台线程 =D。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-30
      • 2016-11-07
      • 1970-01-01
      相关资源
      最近更新 更多