Pregunta

¿Es posible en tiempo de ejecución verificar mediante programación el nombre del subproceso que mantiene el bloqueo de un objeto determinado?

¿Fue útil?

Solución

Sólo puedes saber si el hilo actual tiene un bloqueo normal (Thread.holdsLock(Object)).No se puede obtener una referencia al hilo que tiene el bloqueo sin código nativo.

Sin embargo, si está haciendo algo complicado con los subprocesos, probablemente desee familiarizarse con los paquetes java.util.concurrent.El ReentrantLock le permite obtener su propietario (pero es un método protegido, por lo que tendría que ampliarlo).Dependiendo de su aplicación, es posible que al utilizar los paquetes de concurrencia descubra que, después de todo, no necesita obtener el propietario del bloqueo.

Existen métodos no programáticos para encontrar los propietarios de los bloqueos, como indicarle a la JVM que emita un volcado de subprocesos a stderr, que son útiles para determinar la causa de los interbloqueos.

Otros consejos

Puedes llegar a los mechones sostenidos por hilos con reflejo.Esto sólo funciona con Java 1.6.

ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] ti = bean.getThreadInfo(bean.getAllThreadIds(), true, true);

En cada uno de estos objetos ThreadInfo hay objetos LockInfo que puede usar el identidadHashCode en ellos para compararlos con el bloqueo en cuestión.

Puedes, desde 1.6, usar JMX para hacer todo tipo de cosas interesantes, incluida la búsqueda de cerraduras retenidas.No puede obtener el objeto real, pero sí obtiene el valor hash de clase e identidad (que no es único).

Hay un ejemplo en uno de mis blogs.

Correr jconsola.Está incluido en el SDK de Java y se ejecuta desde la línea de comandos.No estoy seguro de qué sistema operativo estás usando, pero en Windows puedes simplemente pasarle el PID del proceso Java.Debería ayudarle a encontrar el hilo que está causando el problema.O puede utilizar un generador de perfiles comercial como YourKit o cualquier otro generador de perfiles.

En 1.5, puedes encontrar todos los hilos y obtener el estado de cada uno, por ejemplo, así:

    Map<Thread,StackTraceElement[]> map = Thread.getAllStackTraces();
    for (Map.Entry<Thread, StackTraceElement[]> threadEntry : map.entrySet()) {
        log.info("Thread:"+threadEntry.getKey().getName()+":"+threadEntry.getKey().getState());
        for (StackTraceElement element : threadEntry.getValue()) {
            log.info("--> "+element);
        }
    }

Thread.getState le brinda información sobre si el hilo está BLOQUEADO, ESPERANDO, etc., consulte jdk api ThreadState

Puede comprobar el bloqueo del objeto en particular llamando wait() o notify() método en ese objeto.Si el objeto no sujeta el candado, se lanzará. llegalMonitorStateException .

2- Llamando holdsLock(Object o) método.Esto devolverá el valor booleano.

si esto es cerradura de reentrada Puedes comprobar si está retenido por el hilo actual.

final ReentrantLock lock = new ReentrantLock();
lock.isHeldByCurrentThread();

Puede usar una variable para mantener el hilo actual cuando toma el candado y luego imprimirlo si alguien más intenta usarlo.

Thread holderOfLock = null;
Object theLock = new Object();

public void doStuff()
{
    if(holderOfLock != null)
    {
       //get and print name of holderOfLock-thread or get stacktrace etc.
    }

    synchronized (theLock)
    {
        holderOfLock = Thread.currentThread();
        //do stuff...
        holderOfLock = null;
    }
}

Feo pero funciona.

String findLockOwner(ReentrantLock lock) {
    String patternStr = "\\[Locked by thread (\\S+)\\]";
    Pattern pattern = Pattern.compile(patternStr);
    Matcher matcher = pattern.matcher(lock.toString());
    boolean matchFound = matcher.find();
    if (matchFound && matcher.groupCount() >= 1) {
      return matcher.group(1);
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top