这个堆栈转储是否表明我有死锁?

时间:2009-10-23 04:01:47

标签: java concurrency deadlock

我使用Jersey构建了REST服务。

当我对我的REST API执行“curl”时,命令会挂起。

我跑了jstack&这是处于BLOCKED状态的两个线程的汇总输出。

"pool-2-thread-11" prio=6 tid=0x01d51800 nid=0x2394 
 waiting for monitor entry [0x05e6f000..0x05e6fce8]
java.lang.Thread.State: BLOCKED (on object monitor)
    at com.moi.DefaultImageProcessor$DownloadAndScaleCallable.call(
          DefaultImageProcessor.java:168)
    - waiting to lock <0x257aa440> 
     (com.moi.ImageUriMutexImpl$MutexImpl)
      at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
      at java.util.concurrent.FutureTask.run(FutureTask.java:138)
      at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
      at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
      at java.util.concurrent.FutureTask.run(FutureTask.java:138)
     at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(
        ThreadPoolExecutor.java:885)

"pool-2-thread-10" prio=6 tid=0x01d51000 nid=0x18d0
 waiting for monitor entry [0x05e1f000..0x05e1fd68]
java.lang.Thread.State: BLOCKED (on object monitor)
    at com.moi.DefaultImageProcessor$DownloadAndScaleCallable.call(
          DefaultImageProcessor.java:168)
    - waiting to lock <0x257aa6b8> 
     (com.moi.ImageUriMutexImpl$MutexImpl)
      at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
      at java.util.concurrent.FutureTask.run(FutureTask.java:138)
      at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
      at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
      at java.util.concurrent.FutureTask.run(FutureTask.java:138)
     at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(
        ThreadPoolExecutor.java:885)

我想知道如何阅读此堆栈转储。我应该在僵局中寻找什么迹象?

更新我解决了我的问题!基本上我在synchronized块中做了一个HttpClient 4.0 GET。 HttpClient的表现很糟糕&amp;不回来&amp;它抓住了锁。通过jstack,有几个线程持有锁,导致上面的问题。我现在明白这不是死锁,但我的同步块需要很长时间才能返回。

5 个答案:

答案 0 :(得分:5)

从小堆栈跟踪中,线程只等待获取锁定。在跟踪中查找对象0x257aa440和0x257aa6b8,看看谁锁定了这些对象。检查该线程是否被阻止。

在死锁情况下,您会看到阻塞状态的完整圆圈。同时进行多次跟踪以确认阻塞状态是暂时的还是漫长的等待。

答案 1 :(得分:2)

看看this question。这是可以生成的堆栈跟踪的摘录:

"Thread-1" prio=10 tid=0x0841ac00 nid=0x77d waiting for monitor entry [0xb42bf000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at Deadlock$Friend.bowBack(Deadlock.java:16)
    - waiting to lock <0x8b80def8> (a Deadlock$Friend)
    at Deadlock$Friend.bow(Deadlock.java:13)
    - locked <0x8b80df08> (a Deadlock$Friend)
    at Deadlock$2.run(Deadlock.java:28)
    at java.lang.Thread.run(Thread.java:619)

"Thread-0" prio=10 tid=0x08419400 nid=0x77c waiting for monitor entry [0xb4310000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at Deadlock$Friend.bowBack(Deadlock.java:16)
    - waiting to lock <0x8b80df08> (a Deadlock$Friend)
    at Deadlock$Friend.bow(Deadlock.java:13)
    - locked <0x8b80def8> (a Deadlock$Friend)
    at Deadlock$1.run(Deadlock.java:25)
    at java.lang.Thread.run(Thread.java:619)



Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x083f1464 (object 0x8b80def8, a Deadlock$Friend),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x083efc90 (object 0x8b80df08, a Deadlock$Friend),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
    at Deadlock$Friend.bowBack(Deadlock.java:16)
    - waiting to lock <0x8b80def8> (a Deadlock$Friend)
    at Deadlock$Friend.bow(Deadlock.java:13)
    - locked <0x8b80df08> (a Deadlock$Friend)
    at Deadlock$2.run(Deadlock.java:28)
    at java.lang.Thread.run(Thread.java:619)
"Thread-0":
    at Deadlock$Friend.bowBack(Deadlock.java:16)
    - waiting to lock <0x8b80df08> (a Deadlock$Friend)
    at Deadlock$Friend.bow(Deadlock.java:13)
    - locked <0x8b80def8> (a Deadlock$Friend)
    at Deadlock$1.run(Deadlock.java:25)
    at java.lang.Thread.run(Thread.java:619)

Found 1 deadlock.

因此,当您手头有死锁时,VM可以检测并显示它。

答案 2 :(得分:1)

鉴于您注意到该命令“挂起”,并且您已确定在互斥锁上阻塞了两个线程......我会说您正在阅读这些标记......

这实际上取决于您的服务是做什么的。查找性能问题和数据一致性问题。例如,随着请求量的增加,卡住和没有响应,甚至严重的性能命中都是好迹象,可能会出现问题。此外,多个请求之间的数据不一致(同样,取决于您的服务)也可能指向问题。

答案 3 :(得分:1)

jstack很容易发现(常规)死锁 - 它会说有一个死锁。 (例如,可能存在某些情况,例如,线程在彼此等待而不是彼此等待锁定 - EventQueue.invokeAndWait经常导致这种情况。)

我们这里有两个线程块试图锁定不同的对象(标识哈希码为0x257aa440和0x257aa440)。您可能会发现其他线程实际上持有这些锁(只需在文本编辑器中使用find)。可能是监视器很快就被释放而未被关闭的情况。在这种情况下,你可能会看到高度争用的锁。

答案 4 :(得分:0)

这是争用同一资源的两个线程,因此在iself中没有这个不是问题。这可能是问题的一半。

如果这两个线程是唯一被阻止的线程,那么你就不会陷入僵局。死锁(以它最简单的形式)是两个线程,每个线程已经锁定了两个不同的对象,但是每个线程都需要锁定其他对象。

那就是说,仅仅从你提供的内容来看,不是你没有陷入僵局。但是如果事情悬而未决,并且开始得到备份,那么这是一个很好的可能性,但是至少从堆栈转储中确定是不可能的(或者至少是非常困难的)。

编辑:等等,他们没有被锁定在同一件事上。但是两个线程都在同一个函数中。我发现这个(单独)不太可能造成一个,但它可能是导致死锁的线程循环的一部分。