Frage

Warum funktioniert das Prüfprogramm Ergebnis in einem java.lang.IllegalMonitorStateException?

public class test {
    static Integer foo = new Integer(1);
    public static void main(String[] args) {
        synchronized(foo) {
            foo++;
            foo.notifyAll();
        }
        System.err.println("Success");
    }
}

Ergebnis:

Exception in thread "main" java.lang.IllegalMonitorStateException
        at java.lang.Object.notifyAll(Native Method)
        at test.main(test.java:6)
War es hilfreich?

Lösung

Sie haben Recht, dass notifyAll bemerkt muß von einem synchronisierten Block aufgerufen werden.

Doch in Ihrem Fall, weil die Auto-Boxen, auf dem Objekt, das Sie synchronisiert ist nicht das gleiche Beispiel, dass Sie aufgerufen notifyAll auf. In der Tat ist die neue, erhöhte foo Instanz noch auf den Stapel beschränkt, und keine andere Threads möglicherweise auf einem wait Anruf blockiert werden könnten.

Sie können Ihre eigene, veränderbare Zähler implementieren, auf der Synchronisation durchgeführt wird. Je nach Anwendung können Sie auch feststellen, dass die Atomicinteger Ihren Bedürfnissen entspricht.

Andere Tipps

sollte auch sein leery des Verriegelns oder Benachrichtigung auf Objekte wie String und Ganzzahl, die durch die JVM internieren kann (um zu verhindern viele Objekte zu schaffen, die Zahl 1 oder die Zeichenkette „“ darstellen).

die Integer Inkrementieren macht die alten foo verschwinden und mit einem neuen Objekt foo ersetzt werden, die nicht mit dem vorherig foo Variable synchronisiert ist.

Hier ist eine Implementierung von Atomicinteger dass erickson oben vorgeschlagen. In diesem Beispiel foo.notifyAll (); produziert keine java.lang.IllegalMonitorStateException beause das Objekt nicht aktualisiert Atomicinteger wird, wenn foo.incrementAndGet (); ausgeführt wird.

import java.util.concurrent.atomic.AtomicInteger;

public class SynchronizeOnAPrimitive {
    static AtomicInteger foo = new AtomicInteger(1);
    public static void main(String[] args) {
        synchronized (foo) {
            foo.incrementAndGet();
            foo.notifyAll();
        }
        System.out.println("foo is: " + foo);
    }
}

Ausgabe:

foo is: 2

Wie erickson bemerkt hat, funktioniert der Code ohne Postinkrement Operator ohne Fehler:

static Integer foo = new Integer(1);

public static void main(String[] args) {
    synchronized (foo) {
        foo.notifyAll();
    }
    System.out.println("Success");
}

Ausgabe:

  

Erfolg

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top