Указывает ли этот дамп стека, что у меня тупик?

У меня есть служба REST, созданная с использованием Jersey.

Когда я выполнял "завиток" для моего REST API, команда зависает.

Я запустил jstack, и это сводный вывод двух потоков в состоянии ЗАБЛОКИРОВАНО.

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

Я хочу знать, как читать этот дамп стека. Какие признаки нужно искать в тупике?

ОБНОВЛЕНИЕ Я решил свою проблему! В основном я выполняю HttpClient 4.0 GET внутри синхронизированного блока. HttpClient вел себя плохо, не возвращался и держался за замки. Через jstack была пара потоков, удерживающих блокировки, которые вызвали указанную выше проблему. Теперь я понимаю, что это было не столько тупиков, сколько мои синхронизированные блоки возвращались слишком долго.


person Jacques René Mesrine    schedule 23.10.2009    source источник
comment
Они все нормально заблокированы ...   -  person Bostone    schedule 23.10.2009


Ответы (5)


Из небольшой трассировки стека потоки ждут только блокировки. В трассировке найдите объекты 0x257aa440 и 0x257aa6b8 и посмотрите, кто заблокировал эти объекты. Проверьте, не заблокирован ли этот поток.

В тупиковой ситуации вы увидите полный круг заблокированных состояний. Также выполните трассировку несколько раз, чтобы подтвердить, является ли состояние блокировки кратковременным или длительным.

person Bhushan Bhangale    schedule 23.10.2009
comment
ищите объект 0x257aa440: вы имеете в виду поиск потока, который блокирует объект 0x257aa440? (не троллинг, искренне прося точности) - person Nicolas Raoul; 28.06.2012

Взгляните на этот вопрос. Это отрывок из трассировки стека, который можно сгенерировать:

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

Итак, когда у вас есть тупик, виртуальная машина может обнаружить и показать его.

person Bombe    schedule 23.10.2009

Учитывая, что вы замечаете, что команда "зависает", и вы определили два потока, заблокированных на мьютексе ... Я бы сказал, вы довольно хорошо читаете знаки ...

Это действительно зависит от того, что делает ваша служба. Ищите проблемы с производительностью и непротиворечивостью данных. Например, застревание и отсутствие ответа или даже серьезное снижение производительности при увеличении объема запросов - хорошие признаки того, что у вас может быть проблема. Кроме того, несогласованные данные между несколькими запросами (опять же, в зависимости от вашей службы) также могут указывать на проблему.

person Nader Shirazie    schedule 23.10.2009

(Обычный) тупик легко обнаружить с помощью jstack - он скажет, что есть тупик. (Могут быть случаи, когда, например, потоки ожидают друг друга, но не блокируют друг друга - EventQueue.invokeAndWait часто вызывает это.)

У нас есть два блока потоков, пытающихся заблокировать разные объекты (с идентификационными хэш-кодами 0x257aa440 и 0x257aa440). Вы, вероятно, найдете другие потоки, которые действительно удерживают эти блокировки (просто используйте команду find в текстовом редакторе). Может случиться так, что монитор был выпущен очень скоро и не удерживается. В этом случае вы, вероятно, столкнетесь с очень спорными блокировками.

person Tom Hawtin - tackline    schedule 23.10.2009

Это два потока, конкурирующих за один и тот же ресурс, поэтому в iself это не проблема. Хотя это может быть полбеды.

Если только эти два потока заблокированы, значит, вы не в тупике. Тупик (в его простейшей форме) - это когда два потока уже имеют блокировку на двух разных объектах, но каждый из них хочет заблокировать другой.

Тем не менее, исходя из того, что вы предоставили, нет, вы не в тупике. Но если что-то зависает и начинает копироваться, то это хорошая возможность, но это невозможно (или, по крайней мере, очень сложно) точно сказать по дампу стека.

РЕДАКТИРОВАТЬ: Подождите, они не привязаны к одному и тому же. Но оба потока выполняют одну и ту же функцию. Я считаю маловероятным, что это (само по себе) вызовет его, но это может быть частью цикла потоков, вызывающих тупик.

person Matthew Scharley    schedule 23.10.2009