2016-06-13 18 views
2

誰かが私の下でプログラムが終了している理由を理解できますか? 1つのスレッドが別のスレッドが私を読んでいると私は1もプログラムが終了してはならない実際の下に2 でもない価値場合は終了します1と2 で交互に私を更新しているが、それは印刷のいずれか1または2同時読み込みと書き込みの問題

static volatile int i = 1; 

public static void main(String[] args) { 

    new Thread(new Runnable() { 

     @Override 
     public void run() { 
      while (true) { 
       i = (i == 1 ? 2 : 1); 
      } 
     } 
    }).start(); 

    new Thread(new Runnable() { 

     @Override 
     public void run() { 
      while (true) { 
       if (i != 1 && i != 2) { 
        System.out.println("i=" + i); 
        System.exit(0); 
       } 
      } 
     } 
    }).start(); 
} 
出ます
+0

これはJavaで新しい人にとっては良い質問かもしれません:) – CsBalazsHungary

答えて

3

if (i != 1 && i != 2)文で2つのチェック命令があるので、彼らは順番に評価されているので、i != 1が呼び出されたとき、iはとても価値2それはfalseに評価され、i != 2iに呼び出されたときにスイッチバックされているを持っている可能性があります切り替えスレッドによって値1になります。結果としてfalseと評価され、結果としてif (i != 1 && i != 2)は、javaのifの評価が原子ではないため、偽と評価される。

+1

最初のテスト時に 'i!= 1 && i!= 2'という行をチェックして、プログラムが2番目のものをチェックする前の瞬間、もう1つのスレッドはそれを1に切り替えたので、2番目の部分も同様に渡されました。 – CsBalazsHungary

+1

> Javaの整数値の変更はアトミックではありません。私がintについて話していると、私はいつもアトミックであると思っていました。 longの変更は実際には非原子的です。 –

+0

@MikhailKuchmaあなたは正しいです、ありがとう –

2

あなたがif (i != 1 && i != 2)にいるとしましょう。二つの別々のアクションがあります。

  1. read i and compare to 1
  2. read i and compare to 2

iは揮発性であるので、コンパイラ/ VMは、メモリからの両方の時間をプルする必要があります。 (1)が2を読み取り、(2)が1を読み取るシナリオがあります。その場合、System.exitに入ります。

+0

それは揮発性なしでもうまくいきますが、とにかく2つの小切手の間にいくらかのギャップを作るのに役立ちます。 – CsBalazsHungary

+0

はい、そうです。揮発性で、それは起こることが非常に予測可能です。 –

+0

ありがとう、それは今私に意味がある:) –

関連する問題