2

notifyと で飢餓を解決する方法はnotifyall?

4 つのスレッドがあり、同じ obj でロックを取得するのを待っていて、現在のスレッドが呼び出す場合notify()

JVM は任意の 1 つのスレッドを選択します。を呼び出したスレッドはnotify()、JVM によって再び選択される可能性がnotify()あります。

これは、スレッドの 1 つが他のスレッドよりも多く呼び出された場合に飢餓の問題を引き起こす可能性があります。

ここでは、すべてのスレッドの優先度が同じであると想定しています。スレッドの優先度が異なる場合、最も優先度の高いスレッドが選択されると思いますnotify()

また、同じ問題が発生する可能性notifyall()があります。どのスレッドが選択されるかわからない場所だと思います。

4

5 に答える 5

5

どのスレッドが通知されるかが気になる場合は、何か間違ったことをしています。通知を実行する必要がある場合は、通知を待機しているすべてのスレッドがそれを実行できる必要があります。このロジックがユース ケースに当てはまらない場合、ユース ケースにnotifyは適していません。

スレッドの公平性に関する懸念は、通常、コードの設計が不十分であることを示しています。あなたの仕事は、コードが実際に実行したい機能だけを実行し、必要に応じて最も重要な作業を最初に実行するようにすることです。スケジューラが何らかの形でこれを行うことを期待すべきではありません。スケジューラーの仕事は、可能な限り多くの作業を完了させ、プロセス間の優先順位と公平性を強化することです。プログラマーの仕事は、正しい動作をするコードを書くことです。

于 2013-06-12T10:45:32.007 に答える
3

基本的に、スレッドはnotify()関数またはnotifiAll()関数からランダムに選択されます。あなたができることは、ReetrantLockwith Fair ポリシーを使用できることです。公正なポリシーは、スレッドの枯渇を回避します。

private final ReentrantLock lock = new ReentrantLock(true);
于 2013-06-12T10:46:22.070 に答える
1

wait/notify(All) で解決するのは簡単ではありませんが、フェアネスを true に設定して ReentrantLock/Condition を確認できます。ReentrantLock javadoc . ただし、どのスレッドが機能するかは問題ではありません。

于 2013-06-12T10:47:16.813 に答える
0

いいえ、呼び出すスレッドObject.notifyはオブジェクトのロックを所有する必要があり、そのオブジェクトのロックを以前に放棄したスレッドに呼び出しで通知する必要がありますObject.wait。通知スレッドは通知と待機を同時に行うことはできません。

Object.notifyJavaDocから:

目覚めたスレッドは、現在のスレッドがこのオブジェクトのロックを放棄するまで先に進むことができません。目覚めたスレッドは、このオブジェクトの同期をめぐって活発に競合している可能性のある他のスレッドと通常の方法で競合します。たとえば、目覚めたスレッドは、このオブジェクトをロックする次のスレッドになることに関して、信頼できる特権や不利な点を享受しません。

于 2013-06-12T10:49:26.880 に答える