2009-10-12 8 views
28

Warum kann das passieren? Die Sache ist, dass Monitor-Objekt nicht null sicher ist, aber immer noch bekommen wir diese Ausnahme sehr oft:java.lang.IllegalMonitorStateException: (m = null) Fehler beim Abrufen des Monitors für

java.lang.IllegalMonitorStateException: (m=null) Failed to get monitor for (tIdx=60) 
     at java.lang.Object.wait(Object.java:474) 
     at ... 

Der Code, provoziert dies ist eine einfache Pool-Lösung:

public Object takeObject() { 
     Object obj = internalTakeObject(); 
     while (obj == null) { 
      try { 
       available.wait(); 
      } catch (InterruptedException e) { 
       throw new RuntimeException(e); 
      } 
      obj = internalTakeObject(); 
     } 
     return obj; 
    } 

    private Object internalTakeObject() { 
     Object obj = null; 
     synchronized (available) { 
      if (available.size() > 0) { 
       obj = available.keySet().iterator().next(); 
       available.remove(obj); 
       synchronized (taken) { 
        taken.put(obj, Boolean.valueOf(true)); 
       } 
      } 
     } 
     return obj; 
    } 

    public void returnObject(Object obj) { 
     synchronized (taken) { 
      taken.remove(obj); 
     } 
     synchronized (available) { 
      if (available.size() < size) { 
       available.put(obj, Boolean.valueOf(true)); 
       available.notify(); 
      } 
     } 
    } 

bin ich etwas fehlt ?

BEARBEITEN: Die Ausnahme passiert in available.wait(); Zeile.

+0

können Sie uns sagen, welche Zeile 474 im Quellcode ist? – flybywire

+0

Die Ausnahme passiert in available.wait(); Zeile, aber Zeile 474 stammt aus der java.lang.Object-Klasse. –

Antwort

53

Siehe javadoc für Object.wait.

insbesondere "Der aktuelle Thread muss den Monitor dieses Objekts besitzen." und "[throws] IllegalMonitorStateException - wenn der aktuelle Thread nicht der Eigentümer des Monitors des Objekts ist." Das heißt, Sie müssen auf dem Objekt synchronisieren, auf das Sie warten möchten.

so sollte Ihr Code sein:

synchronized (available) { 
    available.wait(); 
} 
+3

Wissenswertes: Verwenden Sie das gleiche Muster, wenn diese Ausnahme bei 'available.notify()' auftritt. –

+0

Ich habe versucht, eine synchronisierte Funktion anstelle eines Blocks zu verwenden, um das Gleiche zu tun, aber es wurde die IllegalMonitorStateException ausgelöst. Warum das? –

+0

Hunter, wenn Sie eine Member-Funktion synchronisiert haben, nehmen Sie eine Sperre für das Objekt - also sollte 'this.wait()' funktionieren. Was hast du genau gemacht? – tgdavies

6

available.wait(); müssen in einem synchronisierten (verfügbar) Abschnitt sein

0

takeObject() -Methode synchronisiert oder werden müssen, müssen wir in diesem Verfahren synchronisierten Block schreiben. Ich hoffe, dass Sie Kompilierungszeit Ausnahme dafür erhalten sollten.

Verwandte Themen