2016-09-24 32 views
0

私は同時に50000000x4マトリックスを満たす4つのスレッドを持っています。書き込みの安全性を保証するために、私はポインタとしてAtomicIntegerを使用しました。各スレッドの各繰り返しは、ポインタ値をthreadPointerにコピーし、それを使用してaを埋めます。 ポインタ== buffer.lengthを取得する最初のスレッドは、バッファをメモリにフラッシュするルーチンを開始します。この時点の他のスレッドは、スレッドがそのジョブを終了するのを待つ必要があります。 これは私のコードです:Javaの待ち受けスレッド

if ((threadPointer = pointer.getAndAdd(1)) >= buffer.length){ 
    synchronized (flag){ 
     if(threadPointer == buffer.length){ 
      sampledSelection(); 
      pointer.set(0); 
      threadPointer = pointer.getAndAdd(1); 
      flag.notifyAll(); 
     }else{ 
      System.out.println("waiting"); 
      flag.wait(); 
      threadPointer = pointer.getAndAdd(1); 
      System.out.println("Awaken!"); 
     } 
    } 
} 

私の問題はnotifyAll()は、私はこの問題を解決することができthreads.How待機を復帰しないということでしょうか?あなたはそれを考え出したよう

+2

'wait'呼び出しで[guarded blocks](https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html)を使用していません。これは競合状態を可能にする。すなわち、あるスレッドが 'wait'呼び出しに到達しようとしているが、まだそれがない場合、別のスレッドは' notifyAll'をあまりにも早く呼び出して、それを永遠に待たせる。 –

+0

私は参照してください。私のコードに予期しない動作を引き起こすバグがあることがわかりました。それらのうちの1つは、スレッドがnotifyAll()を呼び出す前に、あなたが書いたものを引き起こすことを期待しました。ありがとうございました。 – Aalto

答えて

1

それは聞こえるが、後世のために...

私の問題は、のnotifyAllが待機しているスレッドをウェイクアップしないということです。これをどうすれば解決できますか?

ここでは、古典的な競合状態があります。 3スレッドが来て、同じ時刻にpointer.getAndAdd(1)を実行したとしましょう。

  1. スレッド1は、最初にsynchronized (flag)を呼び出し、保護領域に入ります。
  2. スレッド#2とスレッド#3はsynchronized (flag)を呼び出しますが、スレッド#1のロックが解除されるまでロックアウトされます。
  3. スレッド番号1のpointerの値がバッファの長さと等しいので、sampledSelection();を呼び出し、pointerを0にリセットし、notifyAll()を呼び出してロックを解除します。
  4. スレッド#2は、今度は​​セクションに入ります。 pointerの値が等しくないので、ロックを解除するwait()に行きます。
  5. スレッド#3が​​セクションに入ります。 pointerの値が等しくないので、ロックを解除するwait()に行きます。

notifyAll()に電話をかける人がいない場合は、永遠に待機します。

あなたが理解したように、notifyAll()メソッドが動作する唯一の時間は、スレッドががすでに待機している場合です。です。通常、スレッドは条件フィールドを調べて待機する必要があるかどうかを確認する必要があります。

注意すべき点は、​​のオブジェクトが定数であることを確認することです。あなたのflagが問題を引き起こす同じオブジェクトに、その後のスレッドがロック(またはsignalizing)されることはありません別の値に割り当てることができる場合

private final Object flag = new Object(); 

:あなたのケースではflagは次のように定義されるべきです。常にfinalオブジェクトをロックするようにしてください。

これが役に立ちます。

関連する問題