1 つのスレッドが、notify() または NoticeAll() の後に常にオブジェクト ロックを再取得するのはなぜですか?

Mary-Kate Olsen
リリース: 2024-11-24 11:38:10
オリジナル
389 人が閲覧しました

Why Does One Thread Always Reacquire the Object Lock After notify() or notifyAll()?

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;
    }
}
ログイン後にコピー

デッドロック シナリオ:

  1. プロデューサー P1 がオブジェクトをバッファーに置きます。
  2. プロデューサー P2および P3 はオブジェクトを配置しようとしますが、バッファーが存在しないためブロックされます。 full.
  3. コンシューマ C1 はバッファからオブジェクトを取得しようとします。
  4. C1 は実行中でオブジェクトを取得し、待機中のスレッドに通知します。
  5. P2 または C2 は可能です。通知によって目覚めますが、どちらもロックを再取得しようとしてブロックされています。
  6. C3 も取得しようとしてブロックされています。

その結果、3 つのスレッドすべてが無期限に待機し、デッドロックが発生します。

解決策: NoticeAll()

このデッドロックを解決するには、プロデューサ/コンシューマ コードでnotify()の代わりにnotifyAll()を使用する必要があります。これにより、待機中のすべてのスレッドが確実に起動され、デッドロックが防止されます。

推奨事項:

ほとんどのシナリオでは、潜在的なデッドロックを回避するため、notifyAll() が推奨されるメソッドです。特定のシナリオで特定の待機スレッドを 1 つだけ起動する必要がある場合は、notify() を注意して使用できます。

以上が1 つのスレッドが、notify() または NoticeAll() の後に常にオブジェクト ロックを再取得するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート