Pergunta

É possível em tempo de execução verificar programaticamente o nome do Thread que está mantendo o bloqueio de um determinado objeto?

Foi útil?

Solução

Você só pode saber se o thread atual contém um bloqueio normal (Thread.holdsLock(Object)).Você não pode obter uma referência ao thread que possui o bloqueio sem código nativo.

No entanto, se você estiver fazendo algo complicado com threading, provavelmente desejará se familiarizar com os pacotes java.util.concurrent.O ReentrantLock permite que você obtenha seu proprietário (mas é um método protegido, então você teria que estender isso).Dependendo da sua aplicação, pode ser que, ao usar os pacotes de simultaneidade, você descubra que, afinal, não precisa obter o proprietário do bloqueio.

Existem métodos não programáticos para localizar os proprietários do bloqueio, como sinalizar a JVM para emitir um dump de encadeamento para stderr, que são úteis para determinar a causa dos conflitos.

Outras dicas

Você pode chegar às fechaduras presas por fios com reflexão.Isso só funciona com java 1.6.

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

Em cada um desses objetos ThreadInfo existem objetos LockInfo que você pode usar o IdentityHashCode neles para comparar com o bloqueio em questão.

Você pode, a partir da versão 1.6, usar o JMX para fazer todo tipo de coisas interessantes, incluindo encontrar bloqueios retidos.Você não pode obter o objeto real, mas obtém o valor do hash de classe e identidade (que não é exclusivo).

Há um exemplo em um dos meus blogs.

Correr jconsole.Ele está incluído no Java SDK e é executado na linha de comando.Não tenho certeza de qual sistema operacional você está usando, mas no Windows você pode simplesmente passar o PID do processo Java.Deve ajudá-lo a encontrar o tópico que está causando o problema.Ou você pode usar um criador de perfil comercial como YourKit ou qualquer outro criador de perfil.

Na versão 1.5, você pode encontrar todos os threads e obter o estado de cada um, por exemplo, assim:

    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 fornece informações sobre se o thread está BLOQUEADO, ESPERANDO etc., consulte jdk API ThreadState

Você pode verificar o bloqueio de um objeto específico chamando wait() ou notify() método nesse objeto.Se o objeto não segurar a trava, ele lançará llegalMonitorStateException .

2- Ligando holdsLock(Object o) método.Isso retornará o valor booleano.

se for bloqueio reentrante você pode verificar se ele é mantido pelo thread atual

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

Você pode usar uma variável para manter o thread atual ao usar o bloqueio e imprimi-lo se alguém estiver tentando usá-lo.

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

Feio, mas 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top