2008-09-08 91 views
37

是否有可能在运行时以编程方式检查持有给定对象的锁的线程的名称?以编程方式确定哪个Java线程持有锁

+1

请修改您的标题和发布,以表明你的意思是Java可以可以检查。标签不应该是与问题有关的唯一重要信息。 – 2008-09-08 20:24:52

回答

22

您只能分辨当前线程是否保持正常锁定(Thread.holdsLock(Object))。无法获得对没有本机代码的锁定的线程的引用。然而,如果你正在做任何与线程复杂的事情,你可能想要熟悉java.util.concurrent包。 ReentrantLock确实可以让你获得它的所有者(但它是一种受保护的方法,所以你必须扩展它)。根据你的应用程序,很可能通过使用并发包,你会发现你根本不需要获得锁的所有者。

有非编程方法来查找锁拥有者,例如发信号通知JVM向stderr发出线程转储,这对确定死锁的原因很有用。

4

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

7

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

There's an example in one of my weblogs.

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向您提供有关线程是否被阻塞,等待等,请参见jdk api ThreadState

12

您可以通过反射获得线程保持的锁定。这只适用于java 1.6。

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

有关每个ThreadInfo对象有哪些,你可以使用identityHashCode对他们比较有问题的锁LockInfo对象。

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

你可以通过调用wait()或对象notify()方法检查特定对象的锁。如果物体没有锁定,那么它会抛出llegalMonitorStateException

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

1

如果是重新-entrant锁ü如果它是由当前线程保持

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