„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > 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?

Veröffentlicht am 16.11.2024
Durchsuche:758

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 ruft ein Thread das immer wieder ab? Objektsperre?

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

Die Notwendigkeit von notifyAll()

In bestimmten Szenarien jedoch die Verwendung von notify() 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 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 zu platzieren, tun es aber blockiert, weil der Puffer voll ist.
  3. Consumer C1 versucht, ein Objekt aus dem abzurufen Puffer.
  4. C1 wird ausgeführt und ruft das Objekt ab und benachrichtigt dann einen wartenden Thread.
  5. P2 oder C2 können durch die Benachrichtigung geweckt werden, aber beide werden beim Versuch, die Sperre erneut zu erhalten, blockiert .
  6. C3 wird ebenfalls beim Versuch, die Sperre zu erlangen, blockiert.

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 notifyAll() anstelle von notify() im Producer/ verwenden. Verbraucherkodex. 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.

Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3