Heim > Java > javaLernprogramm > Hauptteil

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

Mary-Kate Olsen
Freigeben: 2024-11-24 11:38:10
Original
380 Leute haben es durchsucht

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;
    }
}
Nach dem Login kopieren

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!

Quelle:php.cn
Erklärung dieser Website
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
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage