1. ホーム
  2. java

[解決済み] Java:notify()対notifyAll()の繰り返し

2022-03-25 05:49:50

質問

というキーワードでググると、以下のような違いが出てきます。 notify()notifyAll() "とすると、(javadocの段落は別として)たくさんの説明がポップアップ表示されます。結局のところ、待機中のスレッドの数で決まります。 notify() で、すべて notifyAll() .

しかし(もし私がこれらの方法の違いを正しく理解していれば)、さらなるモニター取得のために選択されるのは常に1つのスレッドだけです。最初のケースではVMによって選択されたものが、2番目のケースではシステムのスレッドスケジューラによって選択されたものが選ばれます。両者の正確な選択手順は、(一般的なケースでは)プログラマにはわかりません。

は何なんだ? 便利 との違い notify() notifyAll() ということでしょうか?何か見落としているのでしょうか?

解決方法は?

<ブロッククオート

しかし、(私がこれらの方法の違いを正しく理解しているならば)、さらなるモニター取得のために常に1つのスレッドのみが選択されます。

それは正しくありません。 o.notifyAll() 目覚め すべて でブロックされているスレッドのうち o.wait() の呼び出しがあります。 スレッドは o.wait() は1つずつですが、それぞれ 意志 順番が回ってくる。


簡単に言うと、スレッドが通知を待っている理由によります。待っているスレッドのうちの1つに何かが起こったことを伝えたいのか、それともすべてのスレッドに同時に伝えたいのか?

場合によっては、待機中のスレッドすべてが、待機が終了した時点で有益な行動をとることができます。例えば、あるタスクの終了を待っているスレッドのセットがあります。タスクが終了すると、待機しているすべてのスレッドがビジネスを続けることができます。このような場合 notifyAll() を使えば、待機しているすべてのスレッドを同時に起動させることができます。

別のケースとして、たとえば排他的ロックの場合、通知された後に待機中のスレッドのうち1つだけが何か役に立つことができます(この場合、ロックを取得します)。このような場合は、むしろ notify() . 正しく実装すると できる 使用 notifyAll() このような場合にも、何もできないスレッドを不必要に起動させてしまうことになります。


多くの場合、条件を待つためのコードはループとして記述されるでしょう。

synchronized(o) {
    while (! IsConditionTrue()) {
        o.wait();
    }
    DoSomethingThatOnlyMakesSenseWhenConditionIsTrue_and_MaybeMakeConditionFalseAgain();
}

そうすれば、もし o.notifyAll() の呼び出しで複数の待機スレッドが発生し、最初に o.wait() が条件を false のままにしておくと、起こされた他のスレッドは待ち状態に戻ってしまいます。