0

2 つのスレッドがあり、Thread2 は Thread1 を待機します (スレッドからメッセージを受信します)。

class Thread1 .. {
 run() {
   synchronized(this) { some-work; notify(); } 
 }
}

class Thread2 .. {
 run() {
   while(true) {
    synchronized(thread1) {
      ...
      thread1.wait();
      ... 
      println("Got here"); // has received the notify() from Thread1   
    }
   }
 }

}

  1. thread2.start() // スレッド 2 は、最初にスレッド 1 からすべてのメッセージを受信する準備ができています
  2. thread1.start()

これらのスレッドをその順序で開始した後、スレッド 2 がスレッド 1 からの notify() を待機している状況が発生し、これは数秒後に発生します。「Got here」というメッセージが表示されます。

しかし、ここで遅延を設定すると:

 class Thread2
 run() {
       while(true) {
        sleep(1000);  // the dalay   
        synchronized(thread1) { ..
 }

その後、'Got Here' というメッセージは表示されません。これは、syncronized(thread1) に到達する前に thread2 が thread1 からの notify() を見逃すためです。

質問は:

1. これらの 2 行はアトミックですか。または、これらの 2 つの行の間のこのギャップはアトミックですか?:

 while(true) {
    // gap
    synchronized(thread1) {..thread.wait() ..} 
 }

2. または、while() と同期ブロックの間に式を入れてはならないということですか? たとえば、次のようになります。

 while(true) {
    int a = 0; a++; 
    synchronized(thread1) {..thread.wait() ..} 

そこにそれらの表現があるため、「待つ必要がない」状況のリスクがありますか?

4

3 に答える 3

2

waitそしてnotify、あなたが発見した理由のために、シグナリングメカニズムを作成するのに十分ではありません:ウェイターがいない場合、通知はビットバケットに入ります。

セマフォで十分です。受信者が他のことをしているときに送信者が許可を返すと、受信者はすぐにその許可を取得します。

ただし、一部のコメント提供者が述べたように、BlockingQueueは、コードがスレッド化について何も知る必要がないことを意味するため、より優れたソリューションです。

于 2013-02-08T15:01:40.813 に答える
1

行間のギャップは「アトミック」であり、アトミック性の概念はここでは適用されません。

通知を見逃さないようにしたい場合は、thread2 の run メソッドの本体で thread1 を開始します。

于 2013-02-08T14:35:07.680 に答える
1

実際、sleep() なしでこれが起こるかどうかを尋ねますよね? 答えはイエスです。「ギャップ」は単なるものですが、ループ自体も実際の命令で構成されています。それらの間で、スレッドが切り替えられる可能性があります。IMHO Thread2.run を最初に開始したからといって、Thread1.run の前に Thread2.run に到達することも保証されていません。ただし、この問題を解決する方法がわかりません。たぶん、スレッド1にスレッド2を待機させますか?

于 2013-02-08T14:36:13.673 に答える