Что такое deadlock?android-33

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

Условия возникновения Deadlock

Для возникновения взаимной блокировки необходимо одновременное выполнение четырех условий (условия Коффмана):

  1. Взаимное исключение: Ресурсы не могут быть разделены между потоками.
  2. Удержание и ожидание: Поток удерживает один ресурс и ждет другой.
  3. Отсутствие вытеснения: Ресурсы нельзя отобрать у потока.
  4. Циклическое ожидание: Существует кольцевая цепочка потоков, где каждый ждет ресурс от следующего.

Пример Deadlock на Java

public class DeadlockExample {
    private static final Object lock1 = new Object();
    private static final Object lock2 = new Object();

    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            synchronized (lock1) {
                System.out.println("Thread 1: Удерживает lock1");
                try { Thread.sleep(100); } catch (InterruptedException e) {}
                synchronized (lock2) {
                    System.out.println("Thread 1: Удерживает lock1 и lock2");
                }
            }
        });

        Thread thread2 = new Thread(() -> {
            synchronized (lock2) {
                System.out.println("Thread 2: Удерживает lock2");
                try { Thread.sleep(100); } catch (InterruptedException e) {}
                synchronized (lock1) {
                    System.out.println("Thread 2: Удерживает lock2 и lock1");
                }
            }
        });

        thread1.start();
        thread2.start();
    }
}

В этом примере:

  1. Thread1 захватывает lock1 и ждет lock2
  2. Thread2 захватывает lock2 и ждет lock1
  3. Оба потока заблокированы навсегда

Как обнаружить Deadlock

  1. Логирование: Анализ логов выполнения
  2. JConsole/VisualVM: Инструменты мониторинга Java
  3. Thread Dump:
    jstack <pid>
    

Способы предотвращения Deadlock

  1. Упорядочивание блокировок: Всегда захватывать ресурсы в одинаковом порядке
    // Правильный подход:
    synchronized(lock1) {
        synchronized(lock2) {
            // код
        }
    }
    
  2. Таймауты: Использовать tryLock() с таймаутом
    if (lock1.tryLock(100, TimeUnit.MILLISECONDS)) {
        try {
            if (lock2.tryLock(100, TimeUnit.MILLISECONDS)) {
                // код
            }
        } finally {
            lock1.unlock();
        }
    }
    
  3. Атомарные операции: Использовать классы из java.util.concurrent.atomic
  4. Отказ от вложенных блокировок: Перепроектировать архитектуру

Deadlock в Android

В Android deadlock особенно опасен, так как может привести к ANR (Application Not Responding). Типичные сценарии:

  • Взаимная блокировка между UI-потоком и фоновыми потоками
  • Блокировки при работе с SharedPreferences
  • Синхронизация при доступе к базе данных

Резюмируем:

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