以编程方式确定哪个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与有问题的锁进行比较。