He notado algo muy extraño ayer. Parece que dos hilos entran en dos bloques sincronizados que bloquean el mismo objeto al mismo tiempo.¡la sección sincronizada no bloquea!
La clase (MyClass
) que contiene el código en cuestión es similar a esto:
private static int[] myLock = new int[0];
protected static int methodA(final long handle, final byte[] sort) {
synchronized (myLock) {
return xsMethodA(handle, sort);
}
}
protected static int methodB(final long handle) {
synchronized (myLock) {
return xsMethodB(handle);
}
}
he creado un vertedero de hilo de mi aplicación que se ejecuta la clase anterior y estaba muy sorprendido cuando vi esto:
"http-8080-136" daemon prio=10 tid=0x00000000447df000 nid=0x70ed waiting for monitor entry [0x00007fd862aea000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.MyClass.methodA(MyClass.java:750)
- locked <0x00007fd8a6b8c790> (a [I)
at com.SomeOtherClass.otherMethod(SomeOtherClass.java:226)
...
"http-8080-111" daemon prio=10 tid=0x00007fd87d1a0000 nid=0x70c8 waiting for monitor entry [0x00007fd86e15f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.MyClass.methodB(MyClass.java:991)
- locked <0x00007fd8a6b8c790> (a [I)
at com.SomeOtherClass.yetAnotherMethod(SomeOtherClass.java:3231)
...
(I cambiaron los nombres de clase y método para el caso de la simplicidad, por lo que no se confundan con los nombres tontos.)
parece que thr ead http-8080-136 y http-8080-111 han adquirido el candado en myLock
. Es el mismo objeto que la dirección del objeto es la misma: 0x00007fd8a6b8c790
. El tiempo de ejecución de Java Especificación dice esto acerca de la palabra clave synchronized
:
Una declaración sincronizado adquiere un bloqueo de exclusión mutua (§17.1) en nombre del subproceso en ejecución, ejecuta un bloque, a continuación, libera el bloqueo. Mientras que el hilo de ejecución posee el candado, ningún otro hilo puede adquirir el candado. [The Java Language Specification, 14.19]
Entonces, ¿cómo es esto posible?
Hay otros 44 hilos en el volcado de hilo "en espera" de la cerradura. Así es como parece que un hilo está esperando:
"http-8080-146" daemon prio=10 tid=0x00007fd786dab000 nid=0x184b waiting for monitor entry [0x00007fd8393b6000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.MyClass.methodC(MyClass.java:750)
- waiting to lock <0x00007fd8a6b8c790> (a [I)
at com.SomeOtherClass.yetAnoterMethod2(SomeOtherClass.java:226)
Mediante el envío de la señal QUIT para el proceso. No sé cómo actúa Sun VM durante el volcado de la hebra. Pero supongo que el proceso se detiene. De lo contrario, obtendría un volcado de hilos incoherente. –
Sé que para IBM JVM esto no es necesariamente cierto, no estoy seguro acerca de SUN, sin embargo, definitivamente algo a tener en cuenta. –
Este sitio reclama que todos los hilos están en pausa: http://expertodev.wordpress.com/2009/05/30/how-to-take-java-thread-dump/ –