是否可以在运行时以编程方式检查持有给定对象锁的线程的名称?
9 回答
您只能判断当前线程是否持有普通锁(Thread.holdsLock(Object)
)。如果没有本机代码,您将无法获得对具有锁的线程的引用。
但是,如果您正在做任何复杂的线程操作,您可能需要熟悉 java.util.concurrent 包。确实允许您获取它的ReentrantLock
所有者(但它是一种受保护的方法,因此您必须扩展它)。根据您的应用程序,很可能通过使用并发包,您会发现根本不需要获取锁的所有者。
有一些非编程的方法可以找到锁的所有者,例如向 JVM 发出信号以向 stderr 发出线程转储,这对于确定死锁的原因很有用。
您可以通过反射获得线程持有的锁。这仅适用于 java 1.6。
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] ti = bean.getThreadInfo(bean.getAllThreadIds(), true, true);
在这些 ThreadInfo 对象中的每一个上都有 LockInfo 对象,您可以使用它们上的 identityHashCode 来与所讨论的锁进行比较。
从 1.6 开始,您可以使用 JMX 做各种有趣的事情,包括查找持有的锁。您无法获得实际对象,但您确实获得了类和身份哈希值(这不是唯一的)。
(这篇文章最初有一个链接到我现在已经失效的博客中的一个例子。)
运行jconsole。它包含在 Java SDK 中并从命令行运行。我不确定您使用的是什么操作系统,但在 Windows 上您可以将 java 进程的 PID 传递给它。它应该可以帮助您找到导致问题的线程。或者,您可以使用诸如 YourKit 之类的商业分析器或任何数量的其他分析器。
在 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
如果它是可重入锁,你可以检查它是否被当前线程持有
final ReentrantLock lock = new ReentrantLock();
lock.isHeldByCurrentThread();
wait()
您可以通过在该对象上调用或notify()
方法来检查特定对象上的锁。如果对象没有持有锁,那么它会抛出llegalMonitorStateException
.
2-通过调用holdsLock(Object o)
方法。这将返回布尔值。
您可以在获取锁时使用变量来保存当前线程,然后在其他人尝试使用它时打印它。
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;
}
}
丑陋但有效。
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);
}
}