Java.lang.IllegalMonitorStateException: (m=null) No se pudo obtener el monitor para


¿Por qué puede suceder esto? La cosa es que el objeto monitor no es nulo con seguridad, pero aún así obtenemos esta excepción bastante a menudo:

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 esto es una solución de pool simple:

    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?

EDITAR : La excepción ocurre en la línea available.wait();.

Author: Esteban Küber, 2009-10-12

3 answers

Ver el objeto javadoc for.Esperen.

En particular "El hilo actual debe poseer el monitor de este objeto."y" [lanza] IllegalMonitorStateException-si el hilo actual no es el propietario del monitor del objeto."Es decir, necesita sincronizar en el objeto que va a llamar a wait on.

Así que su código debe ser:

synchronized (available) {
    available.wait();
}
 60
Author: tgdavies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-12 11:03:13

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

 7
Author: Maurice Perry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-05 12:11:40

El método TakeObject() debe estar sincronizado o, tenemos que escribir bloque sincronizado dentro de este método. Espero que u obtenga una excepción de tiempo de compilación para esto.

 0
Author: prasad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-15 12:46:47