2016-12-02 10 views
-4
package newpackage; 

import java.util.logging.Level; 
import java.util.logging.Logger; 

class test { 

    public int in = 0; 

    void helper() { 

     Thread t1 = new Thread(
       () 
       -> { 

      add(); 

     } 
     ); 

     Thread t2 = new Thread(
       () 
       -> { 

      add(); 

     } 
     ); 
     t1.start(); 
     t2.start(); 
     try { 
      t1.join(); 
      t2.join(); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(test.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    void add() { 
     for (int i = 0; i < 40; i++) { 
      in += i; 
      try { 
       Thread.sleep(50); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(test.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } 

} 

public class Main { 

    public static void main(String[] args) { 
     test a = new test(); 
     a.helper(); 
     System.out.println(a.in); 
    } 
} 

私が望むのは、異なるスレッドから同じメソッドを同時に実行することです。Javaの同じメソッドのマルチスレッド

しかし、上記のコードでは適切な結果が得られません。出力は1560(780 + 780)未満です。どのように達成できますか?

ありがとうございます。

+2

「正しい結果」、予想される出力は何ですか?また、観測される出力は?また、あなたのメソッドは何もしません - 実際のコード、私たちがコンパイル、テスト、修正できるコードを投稿してください。 –

+4

"適切な結果が得られない"私は、あなたが期待している結果が得られないということを意味していると推測しています。あなたはそれが何をすべきだと思いますか、代わりに何をしますか? –

+0

@AndyTurner申し訳ありません。私は簡単にするためにそうしました。今編集されました。ありがとう。 –

答えて

1

あなたは、並行プログラムの古典的な問題の1つに遭遇しました。適切な同期が取れていない変更可能な共有状態。変数inは両方のスレッドによって同時に変更され、さらにi += 1操作はアトミックではありません。実際に何が起こるかです:

int temp = i + 1; 
i = temp; 

問題になりました両方のスレッドを同時に実行するので、何が起こることができますが、このであるということです:あなたは私たちが二回インクリメントしているが、私が唯一持って見ることができるように

// assuming i == 3 
int temp = i + 1; // Thread 1, temp == 4 
int temp = i + 1; // Thread 2, temp == 4 
i = temp; // Thread 2, i == 4 
i = temp; // Thread 1, i == 4 

変数が揮発性でないか、または何もスレッド間で可視性の保証がないため、スレッド1が変数を変更した場合、JVMはその変数を読み取る他のスレッドにその変更を表示させることはできません。

これを正しく行うには、何らかの種類の同期化補助機能を使用する必要があります。最も簡単な方法は、​​ブロックです。しかし、このような場合は、同期をとることで、いくつかのオーバーヘッドを伴って、物事を効果的に順番に実行させるため、物事を並行して追加するという目的を破ることになります。

実際にパラレルに追加したい場合は、Java 8 StreamsまたはJava 7のFork-Join Frameworkを調べてください。ただし、パラレルで実行すると必ず十分な大きさのデータセットが必要ですいくつかのオーバーヘッドがあります。

+0

ありがとう。とった 。次に、add()関数が同じオブジェクト/変数に対して機能しない場合はどうなりますか?私のadd()関数がfileNameのパラメータを受け取り、それに書き込むとします。だから私は別のスレッドから同じ関数に2つの異なるファイル名を渡す場合は、破損の任意の並べ替えがありますか? –

+0

いいえ、別々のファイルへの書き込みは、異なるスレッドから並列に実行できますが、最終的にはこれは基本となるファイルシステムに依存します。 – diesieben07

関連する問題