Указывает ли этот дамп стека, что у меня тупик? - PullRequest
1 голос
/ 23 октября 2009

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

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

Я запустил 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)

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

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

Ответы [ 5 ]

5 голосов
/ 23 октября 2009

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

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

2 голосов
/ 23 октября 2009

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

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

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

1 голос
/ 23 октября 2009

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

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

1 голос
/ 23 октября 2009

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

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

0 голосов
/ 23 октября 2009

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

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

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

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

...