Heim  >  Artikel  >  Java  >  Warum erhält ein Thread nach notify() oder notifyAll() immer wieder die Objektsperre?

Warum erhält ein Thread nach notify() oder notifyAll() immer wieder die Objektsperre?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-11-24 11:38:10383Durchsuche

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

Der subtile Unterschied zwischen notify() und notifyAll()

Der Hauptunterschied zwischen notify() und notifyAll() liegt in der Anzahl der wartenden Threads, die sie aktivieren (einer im Vergleich zu allen), wirft dies eine weitere Frage auf:

Warum aktiviert sich immer ein Thread? Objektsperre erneut erwerben?

Im allgemeinen Fall geben sowohl notify() als auch notifyAll() nicht an, welcher wartende Thread ausgewählt wird, um die Sperre erneut zu erwerben. Die JVM oder der System-Thread-Scheduler treffen diese Auswahl, die nicht deterministisch sein kann.

Die Notwendigkeit von notifyAll()

Allerdings ist in bestimmten Szenarien die Verwendung von notify() erforderlich kann zu einem Deadlock führen, wie das folgende Beispiel zeigt:

Producer/Consumer Class with notify()

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;
    }
}

Deadlock-Szenario:

  1. Produzent P1 legt ein Objekt in den Puffer.
  2. Produzent P2 und P3 versuchen, Objekte abzulegen, werden jedoch blockiert, weil der Puffer voll ist.
  3. Verbraucher C1 versucht, ein Objekt aus dem Puffer abzurufen.
  4. C1 führt das Objekt aus und benachrichtigt dann einen wartenden Thread.
  5. P2 oder C2 können durch die Benachrichtigung geweckt werden, aber beide sind blockiert versucht, die Sperre erneut zu erlangen.
  6. C3 ist ebenfalls blockiert, wenn er versucht, die Sperre zu erlangen.

Als Infolgedessen warten alle drei Threads auf unbestimmte Zeit, was zu einem Deadlock führt.

Die Lösung: notifyAll()

Um diesen Deadlock aufzulösen, muss man stattdessen notifyAll() verwenden notify() im Producer/Consumer-Code. Dadurch wird sichergestellt, dass alle wartenden Threads aktiviert werden, wodurch Deadlocks vermieden werden.

Empfehlung:

Für die meisten Szenarien ist notifyAll() die bevorzugte Methode, da dadurch potenzielle Deadlocks vermieden werden. Wenn das spezifische Szenario das Aufwecken nur eines bestimmten wartenden Threads erfordert, kann notify() mit Vorsicht verwendet werden.

Das obige ist der detaillierte Inhalt vonWarum erhält ein Thread nach notify() oder notifyAll() immer wieder die Objektsperre?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn