44

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

4

9 回答 9

29

您只能判断当前线程是否持有普通锁(Thread.holdsLock(Object))。如果没有本机代码,您将无法获得对具有锁的线程的引用。

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

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

于 2008-09-08T20:21:07.780 回答
18

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

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

在这些 ThreadInfo 对象中的每一个上都有 LockInfo 对象,您可以使用它们上的 identityHashCode 来与所讨论的锁进行比较。

于 2009-09-04T07:40:11.667 回答
7

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

(这篇文章最初有一个链接到我现在已经失效的博客中的一个例子。)

于 2008-09-09T11:02:25.043 回答
4

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

于 2008-09-09T03:40:50.283 回答
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

于 2008-09-09T11:13:36.840 回答
2

如果它是可重入锁,你可以检查它是否被当前线程持有

final ReentrantLock lock = new ReentrantLock();
lock.isHeldByCurrentThread();
于 2015-07-11T16:34:13.177 回答
1

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

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

于 2013-03-07T07:08:22.030 回答
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;
    }
}
于 2011-12-04T23:21:55.207 回答
0

丑陋但有效。

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);
    }
}
于 2018-03-29T06:46:38.003 回答