以编程方式确定哪个Java线程持有锁
是否可以在运行时以编程方式检查持有给定对象的锁的线程的名称?
你只能告诉当前线程是否拥有一个正常的锁( Thread.holdsLock(Object)
)。 你不能得到没有本地代码的锁的线程的引用。
但是,如果你正在做任何与线程复杂的事情,你可能要熟悉java.util.concurrent包。 ReentrantLock
允许你获得它的所有者(但它是一个受保护的方法,所以你必须扩展它)。 根据您的应用程序,很可能通过使用并发包,您会发现您不需要获取锁的所有者。
有非编程方法来查找锁拥有者,例如发信号通知JVM向stderr发出线程转储,这对确定死锁的原因很有用。
你可以通过reflection来获得线程所持有的锁。 这只适用于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。 它应该可以帮助你find导致问题的线程。 或者,您可以使用像YourKit这样的商业分析器或任何其他分析器。
在1.5中,你可以find所有的线程,并获得每个人的状态,例如:
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
您可以通过调用该对象上的wait()
或notify()
方法来检查特定对象上的locking。 如果对象没有保存locking,则会抛出llegalMonitorStateException
。
2-调用holdsLock(Object o)
方法。 这将返回布尔值。
如果是重入锁,你可以检查它是否被当前线程占用
final ReentrantLock lock = new ReentrantLock(); lock.isHeldByCurrentThread();
你可以使用一个variables来保存当前的线程,然后打印它,如果别人正在尝试使用它。
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; } }