2016-05-25 4 views
0

Javaでは、複数のスレッドがそれぞれプリミティブ(ダブル)配列のセクションを分離するために非同期で書き込みを行い、すべてのスレッドが書き込みを完了したときにメインスレッドが配列から読み取ります。配列に同時に書き込むときの可視性の問題

  1. プリミティブ配列のスレッドローカルバージョンを読み書きする機会がありますか?
  2. 1.もし真であれば、これはメインスレッドの読み込みの前にメモリバリアを追加することで解決できますか?どちらをお勧めしますか?

下記のコード例。事前に

多くのおかげで、 マヌエル

//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

それはあなたがローカルのバージョンがintentionally createdない限り、作成されませんスレッド、話している配列(静的なもの)がありますので。すべてのブロックは、同じメモリブロック(アレイのメモリブロック)内のアドレスを読み書きします。書き込みはアレイの別々のセクションに行われるため、data racesは発生しません。他のスレッドによる書き込みが終了した後、メインスレッドによって読み込みが行われると言うので、同期は必要ありません。

+0

ありがとう、スレッドローカルバージョンが作成されない理由を尋ねることができます(私の場合、結果は静的ではありません - ちょうどコードスニペット)。データの競合は起こりませんが、メインスレッドはワーカースレッドのすべての書き込みを読み取ることができると思います。なぜなら、それがその後に発生したとしても?私はいくつかのテストを実行することでこれを観察します。 – user1578796

+0

開始するすべてのワーカースレッドに対して変数のスレッドローカルバージョンが作成された場合、スレッドを使用する必要はなく、ワーカースレッドの結果をメインスレッドの変数に格納する必要があります。スレッドローカルは、スレッドセーフではないオブジェクトがあるのにそのオブジェクトへのアクセスを同期させたくない場合に使用されます。あなたの質問では、 "すべてのスレッドが書き込みを完了したら、メインスレッドは配列から読み込みます。"私が得たことは、ワーカースレッドが完了するまでメインスレッドを一時停止することです。 – pahan

+0

申し訳ありません - 私は "スレッドローカル"の私の使用法はミスリーディングだと思います - 私は、個々のスレッドが結果配列またはそのフィールドをキャッシュし、メインスレッドが配列から読み取るまでフラッシュしないことを意味します。私はThreadLocalのターゲットを絞った使い方について話しているわけではありません。 – user1578796

0

表示の問題があります。それは、各スレッドにローカルコピーがあることを意味するものではありません。つまり、他のスレッドによって書き込まれた値がメインスレッドから見えるという保証はありません。代わりに、私はあなたのエグゼキュータにCallable Sを提出することをお勧め(私はすべてが複数のスレッドの全体の目的を倒すことresult配列へのアクセスの同期の背後にある任意のアイデアを思い付くことができません)メモリバリアを置くしようとしているの

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

各スレッドは独自の結果を返すことができ、メインスレッドはそれらを消費して最終結果を取得します。共有状態の必要はありませんresult

+0

私は、32ビットマシンと64ビットマシンの両方でOPが何年もやっていることをしてきました。今、それが問題になるどこかのマシンがあるかもしれないので、私はそれが起こり得ないと言わないでしょう。私はOPがスレッドの完了を待っているので、どのように見えていないのですか? – edharned

+0

ありがとうございます、合理的に聞こえます - あなたは次の記述を説明するだけですか? >表示の問題があります。それは、各スレッドにローカルコピーがあることを意味するものではありません。つまり、他のスレッドによって書き込まれた値がメインスレッドから見えるという保証はありません。 他のスレッドによる書き込みがないシナリオがありますが、これはスレッドローカルキャッシュとは無関係ですか? – user1578796

関連する問題