当前位置: 首页 > 面试题库 >

线程转储被阻止并锁定

梁存
2023-03-14
问题内容

基本上,我看到了一个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...。另一个问题表明垃圾回收是原因,但是如果是这种情况,不是所有线程都被阻塞了吗?还有其他线程是可运行的。另外,我怎么能证明是这种情况?为什么这是观察到的行为?我不想盲目假设它是垃圾收集器,只是几天后才发现它是其他东西。

==辅助信息==

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

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>因为线程尚未获得相关的锁。

有关更多详细信息,请参见此错误。



 类似资料:
  • 问题内容: 根据Java线程状态信息,调用wait()将导致线程进入BLOCKED状态。但是,这段代码将导致(在调用之后)处于等待状态的线程。 我有什么问题吗?有人可以向我解释这种行为吗?任何帮助,将不胜感激! 问题答案: 线程在等待通知。然后,它变为BLOCKED,试图重新进入同步区域,直到所有其他线程都离开。 您发布的链接中的有关部分(关于WAITING): 例如,在某个对象上调用Object

  • 我有一个小的vertx应用程序。一个超文本传输协议垂直获取一个请求,并通过带有请求-响应模式的eventbus发送它。所以类似于: 在DB Vertical中,我使用消费者获取一条消息,发送到DB,进行一些更改并发送回HTTP verticle。我的问题是,我有一个必须进行大量检查的删除操作,所以这个过程可能需要10秒钟。此时HTTP verticle仍然可以获得一些新请求,但DB consume

  • 我们有一个由2个节点a和B组成的集群。 如果我们在节点a上阻止线程的执行(我是通过远程连接到我的VM并放置断点来执行的),那么节点B认为节点a被分段(这是预期的行为)。 在执行上述场景后,节点A上的任何缓存查找都会被卡住,我们永远不会从IGniteCache中获得结果。 我已经编写了一个测试应用程序来重现这个问题。复制这个问题并不困难,但我已经尽力在readme.md中提供了指导 如果你仍然不清楚

  • 问题内容: 我的Android应用程序中的Java线程有问题。我的嵌套线程阻塞了我的UI,我该如何解决? MyClass.java 这就是我的运行方式: 你可以帮帮我吗?我真的卡住了;) 问题答案: 我的嵌套线程阻止了我的UI 您需要使用而不是。也就是说,更换 与 (这只是一个普通方法。实际上是产生一个新线程并随后运行的方法)

  • 我在健康检查中使用ClusterHealthCheck过程,并且在日志中看到Vertx Thread被阻止的异常。我需要将健康检查作为阻塞代码执行吗? 下面是我用来创建健康检查的代码, 低于例外 我查看了ClusterHealthCheck类,它看起来很简单,从集群管理器获取分区服务并获取集群状态,但不确定为什么需要5秒钟以上才能完成。 我使用的是vertx 4.0.3、hazelcast 4.0