notify() とnotifyAll() の微妙な違い
notify() とnotifyAll() の主な違いは、起動する待機スレッドの数 (1 つとすべて)、これは別の疑問を引き起こします:
なぜ1 つのスレッドが常にオブジェクト ロックを再取得しますか?
一般的な場合、notify() と NotifyAll() の両方は、ロックを再取得するためにどの待機スレッドが選択されるかを指定しません。 JVM またはシステム スレッド スケジューラによってこの選択が行われますが、これは非決定的な場合があります。
notifyAll() の必要性
ただし、特定のシナリオでは、notify() を使用します。次の例に示すように、デッドロックが発生する可能性があります。
Producer/Consumer Class with Notice()
public class ProducerConsumer { private final int MAX_SIZE = 1; // Buffer size private List<Object> buf = new ArrayList<>(); public synchronized void put(Object o) { while (buf.size() == MAX_SIZE) { wait(); } buf.add(o); notify(); } public synchronized Object get() { while (buf.size() == 0) { wait(); } Object o = buf.remove(0); notify(); return o; } }
デッドロック シナリオ:
その結果、3 つのスレッドすべてが無期限に待機し、デッドロックが発生します。
解決策: NoticeAll()
このデッドロックを解決するには、プロデューサ/コンシューマ コードでnotify()の代わりにnotifyAll()を使用する必要があります。これにより、待機中のすべてのスレッドが確実に起動され、デッドロックが防止されます。
推奨事項:
ほとんどのシナリオでは、潜在的なデッドロックを回避するため、notifyAll() が推奨されるメソッドです。特定のシナリオで特定の待機スレッドを 1 つだけ起動する必要がある場合は、notify() を注意して使用できます。
以上が1 つのスレッドが、notify() または NoticeAll() の後に常にオブジェクト ロックを再取得するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。