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

时间:2020-03-05 18:49:37  来源:igfitidea点击:

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

解决方案

回答

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

但是,如果我们要对线程进行任何复杂的处理,则可能需要熟悉java.util.concurrent包。 ReentrantLock确实允许我们获取其所有者(但它是受保护的方法,因此我们必须扩展此方法)。根据应用程序,很可能是通过使用并发包,我们会发现根本不需要获得锁的所有者。

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

回答

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

回答

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

我的一个博客中有一个例子。

回答

在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

回答

我们可以通过反射获得线程持有的锁。这仅适用于Java 1.6.

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

在每个这些ThreadInfo对象上,都有LockInfo对象,我们可以使用它们上的identityHashCode与有问题的锁进行比较。