2016-05-17 58 views
3

我们的Java应用程序与WildFly 8.2.1和Java 1.8_92一起运行,完全挂起在巨大的负载上。在这种情况下,一个threaddump表明,很多线程都在状态的监控0x00000005cc562228等待:如何识别Java中的监视器锁的所有者

"default task-100" #825 prio=5 os_prio=0 tid=0x00000000033a2800 nid=0x49bd in Object.wait() [0x00007f238cb98000] 
    java.lang.Thread.State: WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1465) 
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:644) 
    - locked <0x00000005cc562228> (a com.mchange.v2.resourcepool.BasicResourcePool) 
    at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:554) 
    ....... 

,我们如何才能找到这个监视器锁定的所有者,因为我们假设该线程是一些连接处泄漏的原因是什么?我们假定这个监视器锁定出现在另一个上下文中,但事实并非如此。

或者可能是有任何其他暗示的僵局?任何帮助都非常值得赞赏,因为我们在这个问题上挣扎了很长时间。

+0

它挂起的原因并不是那些线程等待锁定变为可用,而是等待某些内容调用notify(All)并且某些事情可能拥有池中的资源(或忘记通知)。如果锁定被阻止,您会看到类似“等待显示器输入”的内容(例如http://stackoverflow.com/a/11343043)。 – zapl

回答

2

实际上,这是线程(default task-100),它拥有与0x00000005cc562228相对应的锁定,您可以在线程的调用堆栈中看到- locked <0x00000005cc562228>

如果您使用类似JConsole的工具,在Threads选项卡中,您可以使用按钮“Detect Deadlock”检测死锁。

但是在你的情况下,它看起来并不是死锁,因为锁的拥有者显然等待对象池中对象的可用性。我猜它是一个连接池,所以你应该增加连接池的最大大小以避免这种问题。

+0

然而,在增加池大小之前,您应该检查(并测试)连接另一端(以及您的应用程序)的资源是否可以应对增加的连接数。或者修复根本原因,这也可能是另一方的死锁(例如,如果它是数据库,行死锁等)。 – dunni

+0

增加连接池的大小只会延迟应用程序挂起的时间。仔细看一下threaddump会看到超过30个线程在同一个锁对象上等待,堆栈跟踪总是相同的,只有线程ID不同。由于只有一个线程可以成为锁定监视器的所有者,我认为它是一个错字,应该“等待锁定”而不是“锁定”(请参阅​​http://stackoverflow.com/questions/20382091/thread-dump-blocked -and锁定)。 但是很奇怪的是,这个特殊的锁不会出现在threaddump的另一个上下文中。 – user6345319

+0

@ user6345319如果是这样,那么你的代码中可能存在连接泄漏 –