Санкт-Петербургская группа тестирования JVM


« Объявление: Java... | Main | Краткий обзор Java... »
20060421 пятница Апрель 21, 2006

Deadlocks

Что такое deadlock? Это ситуация, когда две конкурирующих программы или нити в программе пытаются использовать общие ресурсы таким образом, что ни одна из них не может продолжить выполнение.

Простейший случай deadlock — это когда нить-1 получает эксклюзивный доступ к ресурсу-1, затем пытается получить доступ к ресурсу-2, который в это время уже эксклюзивно захвачен нитью-2, который в свою очередь пытается получить доступ к ресурсу-1.

Кстати, как можно перевести этот термин на русский язык? Можно найти такие переводы:

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

Deadlock-и могут возникать и в приложениях, и в ядре операционной системы, и в базах данных. При их возникновении нормальная работа приложения становится невозможна, поэтому необходимо заранее избегать ситуации взаимоблокировки или отлеживать возникшие deadlock-и и применять специальные меры. Например, СУБД могут откатывать одну или несколько транзакций, чтобы дать ход остальным. Но как сделать так, чтобы deadlock-и не возникали в программе? Самый простой способ — выбрать порядок захвата общих ресурсов и придерживаться его во всех возможных участках в программе. Тем не менее, в сложных приложениях это не всегда легко, и важной задачей становится обнаружение ситуаций deadlock-а.

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

1: synchronized (lock1) { 2: synchronized (lock2) { 3: // ... 4: } 5: }

а другая:

1: synchronized (lock2) { 2: synchronized (lock1) { 3: // ... 4: } 5: }

Это — потенциальный deadlock. Не факт, что он обязательно возникнет — для этого исполнение этого кода должно произойти таким образом, чтобы нити уже захватив lock1 и lock2 в строке 1, пытались одновременно захватить вторую блокировку (lock2 и lock1, строка 2).

Как обнаружить deadlock в Java программе? К счастью, для этого в JVM есть встроенные средства. Их несколько:

Вот пример программы, которая искуственно создает deadlock и обнаруживает его с помощью ThreadMXBean.findMonitorDeadlockedThreads().

import java.lang.management.*; public class Deadlock { volatile static boolean[] locked = {false, false}; final static String[] resources = {"resource1", "resource2"}; static class DeadlockMakerThread extends Thread { int[] order; DeadlockMakerThread(String name, int[] order) { super(name); this.order = order; } public void run() { // do lock first resource synchronized( resources[order[0]] ) { System.out.println(getName() + ": locked resource: " + resources[order[0]]); locked[order[0]] = true; // wait till second resource will be locked by another thread while (!locked[order[1]]) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } // try to lock second resource (at this time it is already locked by another thread) synchronized( resources[order[1]] ) { System.out.println(getName() + ": locked resource: " + resources[order[1]]); } } } } public static void showDeadlock() { ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); long[] ids = threadMXBean.findMonitorDeadlockedThreads(); if (ids != null) { System.out.print("Deadlocked thread ids: "); for (long id : ids) System.out.print(id + " "); } System.out.println(); } public static void main(String[] args) { int[] order1 = {0, 1}; int[] order2 = {1, 0}; new DeadlockMakerThread("Thread1", order1).start(); new DeadlockMakerThread("Thread2", order2).start(); try { Thread.sleep(1000); } catch (InterruptedException e) { } showDeadlock(); } }

Этот же deadlock обнаруживается при нажатии Ctrl-\ или при использовании JStack.

$ java Deadlock & Thread1: locked resource: resource1 Thread2: locked resource: resource2 Deadlocked thread ids: 8 7 $ jps 14596 Deadlock $ jstack 14596 ... Found one Java-level deadlock: ============================= "Thread2": waiting to lock monitor 0x080a9be8 (object 0xb1e93980, a java.lang.String), which is held by "Thread1" "Thread1": waiting to lock monitor 0x080a9c4c (object 0xb1e939b8, a java.lang.String), which is held by "Thread2" Java stack information for the threads listed above: =================================================== "Thread2": at Deadlock$DeadlockMakerThread.run(Deadlock.java:28) - waiting to lock <0xb1e93980> (a java.lang.String) - locked <0xb1e939b8> (a java.lang.String) "Thread1": at Deadlock$DeadlockMakerThread.run(Deadlock.java:28) - waiting to lock <0xb1e939b8> (a java.lang.String) - locked <0xb1e93980> (a java.lang.String) Found 1 deadlock. ...

А вот что показывает jconsole:

JStack и JConsole более удобны тем, что их можно использовать для работы с уже запущенным приложением. Это особенно полезно при отладке проблем в критической программе (например сервере приложений). К ThreadMXBean также можно получить доступ удаленно, что на самом деле используется в JConsole.

Это не единственная ситуация, когда может возникнуть deadlock. Захват монитора может происходить и в других ситуациях, например внутри блока synchronized при выходе из Object.wait(), при использовании JNI MonitorEnter, и в других случаях. J2SE 5.0 (Tiger) обнаруживает только проблемы связанные с мониторами. А в Java SE 6.0 (Mustang) уже добавлена возможность обнаруживать deadlock-и связанные с новыми блокировками — java.util.concurrent.locks.

Ссылки по теме:

Н.Х.

опубликовал vmrobot ( апр 21 2006, 02:04:33 PM MSD ) Permalink Комментарии [3]

Trackback URL: http://blogs.sun.com/vmrobot/entry/deadlocks
Комментарии:

По поводу русских терминов. Мне кажется что наиболее устоявшийся перевод для deadlock это "тупик", а для thread - "поток" ("нить" это слишком буквально).

опубликовал Dmitry Апрель 21, 2006 at 02:57 PM MSD #

Во многих книгах дедлок переводится как "клинч".

опубликовал ekr Июнь 25, 2006 at 04:39 PM MSD #

Проблема перевода надумана. Говорите "дэдлок", пишите "deadlock" - и вас поймут ВСЕ.

опубликовал somebody Июнь 06, 2007 at 01:09 PM MSD #

Опубликовать комментарий:

Имя
E-Mail:
URL:

Ваш комментарий:

HTML Syntax: Отключен

Хиты страниц за сегодня: 158