以编程方式确定哪个Java线程持有锁

时间:2008-09-08 20:10:56

标签: java multithreading concurrency

是否可以在运行时以编程方式检查持有给定对象锁的Thread的名称?

9 个答案:

答案 0 :(得分:25)

您只能判断当前线程是否保持正常锁定(Thread.holdsLock(Object))。您无法获得对没有本机代码的锁的线程的引用。

但是,如果你正在做任何复杂的线程,你可能想要熟悉java.util.concurrent包。 ReentrantLock允许您获取其所有者(但它是受保护的方法,因此您必须扩展它)。根据您的应用程序,很可能通过使用并发软件包,您会发现毕竟不需要获取锁的所有者。

有一些非编程方法可以找到锁所有者,例如发信号通知JVM向stderr发出线程转储,这对于确定死锁的原因非常有用。

答案 1 :(得分:14)

你可以通过反射获得线程所持有的锁。这仅适用于java 1.6。

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

在每个ThreadInfo对象上都有LockInfo对象,你可以使用它们上的identityHashCode来比较有问题的锁。

答案 2 :(得分:7)

你可以从1.6开始使用JMX做各种有趣的事情,包括查找持有的锁。你无法获得实际的对象,但你确实得到了类和身份哈希值(这不是唯一的)。

There's an example in one of my weblogs.

答案 3 :(得分:4)

运行jconsole。它包含在Java SDK中,并从命令行运行。我不确定你使用的是什么操作系统,但是在Windows上你可以将它传递给java进程的PID。它应该可以帮助您找到导致问题的线程。或者,您可以使用像YourKit这样的商业分析器或任何其他分析器。

答案 4 :(得分:3)

在1.5中,您可以找到所有线程并获取每个线程的状态,例如:

    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为您提供有关线程是否为BLOCKED,WAITING等的信息,请参阅jdk api ThreadState

答案 5 :(得分:1)

您可以通过调用该对象上的wait()notify()方法来检查特定对象的锁定。如果对象没有锁定,那么它将抛出llegalMonitorStateException

2-通过调用holdsLock(Object o)方法。这将返回布尔值。

答案 6 :(得分:1)

如果是重新锁定你可以检查它是否被当前线程保留

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

答案 7 :(得分:0)

您可以使用变量来锁定当前线程,然后在其他人尝试使用时打印它。

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

答案 8 :(得分:-1)

丑陋但有效。

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