2009-10-12 6 views
28

¿Por qué puede suceder esto? El caso es que monitor objeto no es nulo a ciencia cierta, pero aún así obtener esta excepción con bastante frecuencia:java.lang.IllegalMonitorStateException: (m = null) Error al obtener el monitor

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

el código que provoca esta es una solución simple piscina:

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

Me estoy perdiendo algo ?

EDIT: La excepción se produce en la línea available.wait();.

+0

¿Puede decirnos qué línea es 474 en el código fuente? – flybywire

+0

la excepción ocurre en available.wait(); línea, pero la línea 474 es de la clase java.lang.Object. –

Respuesta

53

Ver la Javadoc para Object.wait.

en particular "El hilo actual debe ser el propietario del monitor de este objeto". y "[arroja] IllegalMonitorStateException - si el hilo actual no es el propietario del monitor del objeto". Es decir, debe sincronizar en el objeto al que va a llamar esperar.

lo que el código debe ser:

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

Merece la pena saberlo: use el mismo patrón si esta excepción ocurre en 'available.notify()'. –

+0

Intenté usar una función sincronizada en lugar de un bloque para hacer lo mismo, pero arrojó la IllegalMonitorStateException. ¿Porqué es eso? –

+0

Hunter, cuando sincroniza una función miembro, está bloqueando el objeto, por lo que 'this.wait()' debería funcionar. ¿Que hiciste exactamente? – tgdavies

6

available.wait(); debe estar en una sección sincronizada (disponible)

0

takeObject() método debe ser sincronizada o, tenemos que escribir bloque sincronizado dentro de este método. Espero que consigas una excepción de tiempo de compilación para esto.

Cuestiones relacionadas