「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > 1 つのスレッドが、notify() または NoticeAll() の後に常にオブジェクト ロックを再取得するのはなぜですか?

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

2024 年 11 月 16 日に公開
ブラウズ:723

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

notify() と NoticeAll() の微妙な違い

Notify() と NoticeAll() の主な違いは、起動する待機スレッドの数 (1 つとすべて)、これにより別の疑問が生じます:

なぜ 1 つのスレッドが常にオブジェクト ロックを再取得するのですか?

一般的にこの場合、notify() と NoticeAll() の両方で、ロックを再取得するためにどの待機スレッドが選択されるかは指定されません。 JVM またはシステム スレッド スケジューラによってこの選択が行われますが、これは非決定的な場合があります。

notifyAll() の必要性

ただし、特定のシナリオでは Notice() を使用します。次の例に示すように、デッドロックが発生する可能性があります。

Producer/Consumer Class with Notice()

public class ProducerConsumer {

    private final int MAX_SIZE = 1;  // Buffer size

    private List 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 はオブジェクトを配置しようとしますが、バッファがいっぱいのためブロックされました。
  3. コンシューマ C1 はバッファからオブジェクトを取得しようとしています。
  4. C1 は実行中でオブジェクトを取得し、待機中のスレッドに通知します。
  5. P2 または C2 は通知によって起動できますが、両方ともロックを再取得しようとしてブロックされます。
  6. C3 もロックを取得しようとしてブロックされます。

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

解決策:notifyAll()

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

推奨事項:

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

最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3