Обнаружение мертвой блокировки в Java

62
задан Warren Dew 29 August 2015 в 15:34
поделиться

12 ответов

Начиная с JDK 1.5 там очень полезные методы в java.lang.management пакет, чтобы найти и осмотреть мертвые блокировки, который происходит. Посмотрите findMonitorDeadlockedThreads() и findDeadlockedThreads() метод ThreadMXBean класс.

А возможный способ использовать это должно иметь отдельный сторожевой поток (или периодическая задача), который делает это.

Пример кода:

  ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
  long[] ids = tmx.findDeadlockedThreads();
  if (ids != null) {
     ThreadInfo[] infos = tmx.getThreadInfo(ids, true, true);
     System.out.println("The following threads are deadlocked:");
     for (ThreadInfo ti : infos) {
        System.out.println(ti);
     }
  }
79
ответ дан staffan 24 November 2019 в 16:41
поделиться

Если Вы отлаживаете в затмении, можно приостановиться, приложение (выберите приложение в представлении отладки и мало || кнопка на панели инструментов отладки), и затем это может сообщить о мертвых блокировках.

См. http://runnerwhocodes.blogspot.com/2007/10/deadlock-detection-with-eclipse.html для примера.

2
ответ дан Scott Stanchfield 24 November 2019 в 16:41
поделиться

Доктор Heinz Kabutz из JavaSpecialists записал интересное и информативное проблема новостной рассылки о мертвых блокировках Java и описывает что-то позвонившее ThreadMXBean в другой выпуск новостной рассылки. Между теми необходимо получить хорошую идею проблем и некоторых указателей на выполнение собственного инструментария.

3
ответ дан user29480 24 November 2019 в 16:41
поделиться

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

Даже обеденная проблема философов может рассматриваться как нарушение этого правила, поскольку это использует относительное понятие левой и правой ложки, которое приводит к различным потокам с помощью различных заказов выделения ложек. Если бы ложки были пронумерованы исключительно и философы, все пытались получить самую низкую пронумерованную ложку сначала, мертвая блокировка была бы невозможна.

, По-моему, предотвращение лучше, чем средство исправления.

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

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

4
ответ дан paxdiablo 24 November 2019 в 16:41
поделиться

Если Вы работаете от командной строки, и Вы подозреваете, что заведены в тупик, попробуйте ctrl+break в окнах (ctrl +\в Unix) для получения дампа потока. См. http://java.sun.com/javase/6/webnotes/trouble/TSG-VM/html/gbmps.html

3
ответ дан Paul Croarkin 24 November 2019 в 16:41
поделиться

Если Вы находитесь на Java 5, можно назвать метод findMonitorDeadlockedThreads() на ThreadMXBean, который можно пройти через вызов java.lang.management.ManagementFactory.getThreadMXBean(). Это найдет мертвые блокировки вызванными объектными мониторами только. На Java 6 существует findDeadlockedThreads(), который также найдет мертвые блокировки вызванными "ownable синхронизаторами (например ReentrandLock и ReentrantReadWriteLock).

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

4
ответ дан WMR 24 November 2019 в 16:41
поделиться

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

я предложил бы мигрировать на использование java.util.concurrent. Блокировка блокирует и т.п. для создания схем блокировки легче рассуждать о. На самом деле Вы могли легко сделать свою собственную реализацию интерфейса блокировки с обнаружением мертвой блокировки. Алгоритм должен в основном пересечь граф зависимостей блокировки и искать цикл.

6
ответ дан Adam Bellaire 24 November 2019 в 16:41
поделиться

JDK 5 и 6 выведет содержимую информацию блокировки в полном дампе потока (полученный с уничтожением-3, jstack, jconsole, и т.д.). JDK 6 даже содержит информацию о ReentrantLock и ReentrantReadWriteLock. Возможно от этой информации диагностировать мертвую блокировку путем нахождения цикла блокировки: A Потока содержит блокировку 1, Поток B содержит блокировку 2, и или A запрашивает 2 или B, запрашивает 1. На основе моего опыта это обычно довольно очевидно.

Другие аналитические инструменты могут на самом деле найти потенциальные мертвые блокировки, даже если они не происходят. Инструменты потока от поставщиков как OptimizeIt, JProbe, Coverity, и т.д. являются хорошими местами для взгляда.

11
ответ дан Alex Miller 24 November 2019 в 16:41
поделиться

JConsole в состоянии обнаружить мертвые блокировки в запущенном приложении.

18
ответ дан Steve K 24 November 2019 в 16:41
поделиться

Не точно, что Вы спросили, но когда мертвая блокировка делает , происходят, можно сделать, "уничтожают-3" на идентификаторе процесса, и это выводит дамп потока к stdout. Кроме того, 1.6 jvm имеет некоторые инструменты, чтобы сделать то же самое gui способом.

3
ответ дан Paul Tomblin 24 November 2019 в 16:41
поделиться

Обратите внимание, что существует тип взаимоблокировки с использованием параллельного пакета, который очень трудно отлаживать. Вот где у вас есть ReentrantReadWriteLock, и один поток захватывает блокировку чтения, а затем (скажем) пытается войти в монитор, удерживаемый каким-то другим потоком, который также ожидает захвата блокировки записи. Что особенно затрудняет отладку, так это отсутствие записи о том, кто ввел блокировку чтения. Это просто счет. Поток мог даже вызвать исключение и умереть, оставив счетчик чтения ненулевым.

Вот пример тупиковой ситуации, которую метод findDeadlockedThreads, упомянутый ранее, не получит:

import java.util.concurrent.locks.*;
import java.lang.management.*;

public class LockTest {

    static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public static void main(String[] args) throws Exception {
        Reader reader = new Reader();
        Writer writer = new Writer();
        sleep(10);
        System.out.println("finding deadlocked threads");
        ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
        long[] ids = tmx.findDeadlockedThreads();
        if (ids != null) {
            ThreadInfo[] infos = tmx.getThreadInfo(ids, true, true);
            System.out.println("the following threads are deadlocked:");
            for (ThreadInfo ti : infos) {
                System.out.println(ti);
            }
        }
        System.out.println("finished finding deadlocked threads");
    }

    static void sleep(int seconds) {
        try {
            Thread.currentThread().sleep(seconds*1000);
        } catch (InterruptedException e) {}
    }

    static class Reader implements Runnable {
        Reader() {
            new Thread(this).start();
        }
        public void run() {
            sleep(2);
            System.out.println("reader thread getting lock");
            lock.readLock().lock();
            System.out.println("reader thread got lock");
            synchronized (lock) {
                System.out.println("reader thread inside monitor!");
                lock.readLock().unlock();
            }
        }
    }

    static class Writer implements Runnable {
        Writer() {
            new Thread(this).start();
        }
        public void run() {
            synchronized (lock) {
                sleep(4);
                System.out.println("writer thread getting lock");
                lock.writeLock().lock();
                System.out.println("writer thread got lock!");
            }
        }
    }
}
8
ответ дан 24 November 2019 в 16:41
поделиться

Спустя столько времени я могу написать простейший пример тупика. Комментарии приветствуются.

Class A
{
  synchronized void methodA(B b)
  {
    b.last();
  }

  synchronized void last()
  {
    SOP(“ Inside A.last()”);
  }
}

Class B
{
  synchronized void methodB(A a)
  {
    a.last();
  }

  synchronized void last()
  {
    SOP(“ Inside B.last()”);
  }
}


Class Deadlock implements Runnable 
{
  A a = new A(); 
  B b = new B();

  // Constructor
  Deadlock()
  {
    Thread t = new Thread(); 
    t.start();
    a.methodA(b);
  }

  public void run()
  {
    b.methodB(a);
  }

  public static void main(String args[] )
  {
    new Deadlock();
  }
}
-1
ответ дан 24 November 2019 в 16:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: