繁体   English   中英

线程转储被阻止并锁定

[英]Thread dump blocked AND locked

这类似于Java线程转储:没有“等待锁定...”的BLOCKED线程

基本上,我看到一个BLOCKED线程,但它有等待的锁:

"pool-1-thread-60" prio=10 tid=0x00007fbf10017000 nid=0x210 waiting for monitor entry [0x00007fbed64e3000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at org.apache.log4j.Category.callAppenders(Category.java:204)
        - locked <0x0000000742444ad0> (a org.apache.log4j.Logger)
        at org.apache.log4j.Category.forcedLog(Category.java:391)
        at org.apache.log4j.Category.info(Category.java:666)
        ...

我希望看到- waiting to lock <0x0000000742444ad0>...而不是- locked... 另一个问题表明垃圾收集是原因,但如果是这样的话,不是所有线程都被阻塞了吗? 还有其他线程是RUNNABLE。 另外,我怎么能证明这种情况呢? 为什么这是观察到的行为? 我不想盲目地假设它是垃圾收集器只是为了发现几天之后它是别的东西。

==辅助信息==

虽然我认为它与手头的问题无关,但这是上述转储来自的代码部分。

for(Category c = this; c != null; c=c.parent) {
  // Protected against simultaneous call to addAppender, removeAppender,...
  synchronized(c) { //line 204
if(c.aai != null) {
  writes += c.aai.appendLoopOnAppenders(event);
}
if(!c.additive) {
  break;
}
  }
}

显然,需要在该线路上获得锁定。 但是,当一个线程在此监视器上被真正阻塞时,线程转储中的输出显示为(这来自同一个转储):

"pool-1-thread-44" prio=10 tid=0x00007fbef0051000 nid=0x200 waiting for monitor\
 entry [0x00007fbed74f3000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at org.apache.log4j.Category.callAppenders(Category.java:204)
        - waiting to lock <0x0000000742444ad0> (a org.apache.log4j.Logger)
        at org.apache.log4j.Category.forcedLog(Category.java:391)
        at org.apache.log4j.Category.info(Category.java:666)
        ...

我感兴趣的转储部分看起来不同(“锁定”而不是“等待锁定”)。 我调试了很多死锁并查看了很多线程转储。 我总是看到的是“等待锁定”。 我从未见过一个被“锁定”但仍在“等待监视器进入”的线程,我想知道这意味着什么。

这是Oracle HotSpot JVM中一个已知的化妆品错误。 如你所说,在您看到的堆栈跟踪中- locked <0x00007f3e9a0b3830>它实际上应该说- waiting to lock <0x00007f3e9a0b3830>因为线程尚未获得相关锁。

有关详细信息,请参阅此错误

在每个Logger上获取锁定,同时迭代其appender以防止对appender集合进行并发更改。 如果在appender中阻塞了一个线程(例如,通过网络连接写入事件),则记录到该Logger实例的其他线程必须等待锁定。 AsyncAppender可用于缓冲事件并最大限度地减少争用,但可能会丢失缓冲区中的事件。

奇怪的是,你不是看到“锁定” 而不是 “等待锁定”,而是除了 “锁定” 之外你没有看到“等待锁定”。 也就是说,看起来有问题的线程是赢得比赛以获取给定类别的日志的线程,现在正在等待获取对其他对象的额外锁定。 那么,这个谜就是为什么转储不识别另一个对象?

我认为你的假设是它已经拥有锁定的Logger是不正确的。

还在想你正在使用的确切版本是什么?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM