【问题标题】:How to identify the owner of a monitor lock in Java如何在 Java 中识别监视器锁的所有者
【发布时间】:2016-09-13 13:44:27
【问题描述】:

我们使用 WildFly 8.2.1 和 Java 1.8_92 运行的 Java 应用程序在巨大的负载下完全挂起。这种情况下的线程转储显示,在监视器 0x00000005cc562228 处有很多线程处于 WAITING 状态:

"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)
    .......

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

或者对于死锁情况可能有任何其他提示?非常感谢任何帮助,因为我们在这个问题上苦苦挣扎了很长时间。

【问题讨论】:

  • 它挂起的原因不是那些线程等待锁变得可用,它们等待调用 notify(All) 的东西以及可能拥有池中的资源的东西(或忘记通知)。如果锁被阻止,您会看到类似“等待监视器进入”的内容(例如在 stackoverflow.com/a/11343043 中)。

标签: java multithreading wildfly connection-leaks


【解决方案1】:

实际上这是拥有与0x00000005cc562228 对应的锁的线程(default task-100),这要感谢线程调用堆栈中的- locked &lt;0x00000005cc562228&gt;

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

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

【讨论】:

  • 在增加池大小之前,您应该检查(并测试)连接另一端的资源(和您的应用程序)是否可以应对增加的连接数。或者修复根本原因,这也可能是另一边的死锁(例如,如果它是数据库,行的死锁等)。
  • 增加连接池的大小只会延迟应用程序挂起的时间。仔细查看 threaddump 会发现超过 30 个线程在同一个锁对象处等待,堆栈跟踪始终相同,只是线程 ID 不同。由于只有一个线程可以是锁监视器的所有者,我认为这是一个错字,应该是“等待锁定”而不是“锁定”(参见stackoverflow.com/questions/20382091/…)。但是很奇怪的是,这个特殊的锁并没有出现在threaddump的另一个上下文中。
  • @user6345319 如果是这样,那么您的代码中可能存在连接泄漏
猜你喜欢
  • 2011-07-05
  • 2018-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多