2016-12-03 12 views
-1
public class RunTest { 
    public static int counter = 0; 
    static class RunnerDec implements Runnable{ 
     public void run(){ 
      for(int i=0;i<5000; i++){ 
       counter--; 
      } 
     } 
    } 

    static class RunnerInc implements Runnable{ 
     public void run(){ 
      for(int i=0;i<5000; i++){ 
       counter++; 
      } 
     } 
    } 

    public static void main(String[] args) { 
     RunnerDec rd = new RunnerDec(); 
     RunnerInc ri = new RunnerInc(); 
     Thread t1 = new Thread(rd); 
     Thread t2 = new Thread(ri); 
     t1.start();  
     t2.start(); 
     try{ 
      t1.join(); // this will stop the main thread until t1 is done incrementing 5000 times 
      t2.join(); // this will stop the main thread until t2 is done incrementing 5000 times 
     }catch(Exception e){ 
      e.printStackTrace(); 
     } 
     System.out.println(counter); 
    } 

} 

に参加私はこれが当てはまらない悲しいかな、結果は毎回0であることを期待しています。 Java docはjoin()が "このスレッドが死ぬのを待つ"と述べています。私はメインスレッドがt1が終了してからt2が完了するのを待つ必要があるように感じます。それは起こっていることではありません。明快さに感謝します!のJavaスレッドは()の挙動

+0

「スタート」はどう思いますか? –

答えて

2

スレッドが終了するのを待ちます。しかし、あなたの2つのスレッドは、同期なしで共有変数を同時に更新するので、競合状態と可視性の問題が発生しています。例えば

counter = 1000 
thread 1 reads counter : 1000 
thread 2 reads counter : 1000 
thread 1 increments and writes counter: 1001 
thread 2 decrements and writes counter: 999 

ため++および - アトミック操作ではないが、一例をインターレース上記スレッドはインクリメントを失います。

これらを修正する最も簡単な方法は、intではなくAtomicIntegerを使用することです。問題の要点を理解するには、Java Concurrency in Practiceを読むか、少なくともJavaの同時実行チュートリアルを読むのがよいでしょう。