是否可以在运行时以编程方式检查持有给定对象锁的Thread的名称?
答案 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做各种有趣的事情,包括查找持有的锁。你无法获得实际的对象,但你确实得到了类和身份哈希值(这不是唯一的)。
答案 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);
}
}