2

ThreadBからスレッドに通知を送信し、からThreadAの通知を待機する機能があります。ThreadAThreadB

の間の期間中Aは によって通知されB、次にBによってデータがA ThreadA読み取られThreadB、終了すると に通知が送信されThreadBます。

sendNotifyAndWaitNotify は ThreadB で実行されます。

同じオブジェクトで1つずつ同期するのは奇妙に見えるかもしれませんが、B.sync.notify();同期ブロックを終了したときにのみ通知を送信し、1つのブロックにすべてを書き込む場合は、最初に待機し、同期ブロックを終了したときにのみ通知を送信します。それは受け入れられません。

void sendNotifyAndWaitNotify() {
    synchronized(B.sync) {
        B.sync.notify();
    }
    //ThreadA reads ThreadB data
    synchronized (B.sync) {     
        try {
            debug("start waiting for notify");
            B.sync.wait();
        } catch (Exception e) {
            error( e.toString());
        }
    }
    debug("reader sleep done");
}

しかし、この関数は正しくありません。なぜなら、ThreadB が待機を開始していない時点で、ThreadA はデータを読み取り、ThreadB に通知できるからです。次のような同期ブロックをまたいで問題を解決することは可能ですか:

void sendNotifyAndWaitNotify() 
   {
   synchronized(B.sync) // block #1
      {
      synchronized(B.sync)  // block #2
         {
         B.sync.notify();
         }

   //ThreadA reads ThreadB data

      try 
         {
         debug("start waiting for notify");
         B.sync.wait();
         } catch (Exception e) {
         error( e.toString());
         }
      debug("reader sleep done");
      }
   }

同期ブロック #1 を終了した後、#2 ではなく ThreadA が起動されることを期待しています。そして、ブロック#2のコードは、おそらく2番目のブロックは別の同期オブジェクトで作成する方がよいと思いますか?

Java 1.4 を使用する必要があります。

4

2 に答える 2

1

wait()ループ条件での呼び出しは常に保護する必要があります。

synchronized(B.sync){
    while(!myConditionIsSatisfied){
        B.sync.wait();
    }
    /* Do critical stuff */
}

そうすれば、スレッドが同期ブロックに到達するまでに条件がすでに満たされている場合、スレッドは何も待機しません。

ループ状態で待機を保護するもう 1 つの理由は、コントラクトによって誤っwait()てウェイクアップすることが許可されていることです。その場合、条件が満たされない場合は、スレッドを に送り返します。wait()

参照: Object.wait(long) の JavaDoc Object.wait() は Object.wait(0) の呼び出しです

抜粋(強調鉱山):

スレッドは、通知、中断、またはタイムアウトなしでウェイクアップすることもできます。これは、いわゆるスプリアス ウェイクアップです。これが実際に発生することはめったにありませんが、アプリケーションは、スレッドが起動される原因となったはずの条件をテストし、条件が満たされない場合は待機し続けることで、これを防ぐ必要があります。言い換えれば、 待機は次のように loops で常に発生する必要があります。

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait(timeout);
     ... // Perform action appropriate to condition
 }
于 2013-09-27T13:45:36.257 に答える