2010-01-12 17 views
13

¿Qué puede causar que me sale IllegalMonitorStateException en este códigoIllegalMonitorStateException

synchronized(syncCount){ 
    syncCount--; 
    syncCount.notify(); 
} 

estoy algo confundido, ya que, por lo que yo sé correr hilo debe tener el monitor en el objeto que está notificar que se llama. Me parece que mi código no puede estar equivocado, pero de alguna manera lo es.

Respuesta

23

del tipo Integer o similar? -- reemplaza el objeto inmutable Integer con otro. Por lo tanto, está llamando al notify en un objeto diferente al synchronized.

Su código es el equivalente a:

Integer syncConunt = Integer.valueOf(5); 
[...] 
synchronized (syncCount) { 
    syncCount = Integer.valueOf(syncCount.intValue() + 1); 
    syncCount.notify(); 
} 

Usted no está solo. Incluso antes de J2SE 5.0, he visto código de ejemplo publicado en un libro que asignó una referencia dentro de un bloque sincronizado. En general, es una buena idea marcar los campos de bloqueo final.

Otro punto importante es que el código se sincroniza en un objeto que no "posee". Integer se comparten los objetos (Integer.valueOf(int) devolverá exactamente la misma instancia si se llama con valores entre -128 y 127, y tal vez más). Si esto fuera hecho por dos piezas de código no relacionado, entonces habría interacciones ocultas. Esto se aplica a cualquier tipo en el que las instancias se compartan entre código no relacionado. Los ejemplos comunes son Integer, String, Class (utilizado por métodos estáticos sincronizados) y Thread (en la implementación de Sun, Thread pasa a usarse como cerradura para join).

+1

Muchas gracias. Esto resuelve el problema. –

+0

Puede resolver la excepción lanzada, pero debe comprender lo que dice Tom al declarar el campo final. No es seguro declarar un nuevo objeto en su propio bloque sincronizado –

+1

gran error de concurrencia. –