← Назад к вопросам

Приведи пример DeadLock

2.7 Senior🔥 102 комментариев
#Многопоточность и асинхронность

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Пример Deadlock в Android/Java

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

Ключевые условия возникновения Deadlock

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

  1. Взаимное исключение — ресурс не может использоваться несколькими потоками одновременно
  2. Удержание и ожидание — поток удерживает один ресурс и ждет другой
  3. Отсутствие вытеснения — ресурс нельзя отнять у потока
  4. Круговая зависимость — циклическая цепочка ожидающих потоков

Практический пример Deadlock в Android

class DeadlockExample {
    private val lockA = Object()
    private val lockB = Object()
    private var counterA = 0
    private var counterB = 0

    fun startDeadlock() {
        // Поток 1: захватывает lockA, затем пытается захватить lockB
        Thread {
            synchronized(lockA) {
                println("Поток 1: захватил lockA")
                Thread.sleep(100) // Имитация работы
                
                synchronized(lockB) {
                    println("Поток 1: захватил lockB")
                    counterA += counterB
                }
            }
        }.start()

        // Поток 2: захватывает lockB, затем пытается захватить lockA
        Thread {
            synchronized(lockB) {
                println("Поток 2: захватил lockB")
                Thread.sleep(100) // Имитация работы
                
                synchronized(lockA) {
                    println("Поток 2: захватил lockA")
                    counterB += counterA
                }
            }
        }.start()
    }
}

// Использование в Android Activity/Fragment
class ExampleFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // Запуск deadlock через некоторое время
        view.postDelayed({
            DeadlockExample().startDeadlock()
        }, 1000)
    }
}

Более реалистичный пример с ресурсами Android

class ResourceDeadlockExample {
    private val databaseLock = Any()
    private val networkLock = Any()
    private val sharedList = mutableListOf<String>()

    fun updateDataFromNetworkAndDatabase() {
        // Поток для обработки данных из сети
        thread {
            synchronized(networkLock) {
                println("Сетевой поток: блокировка сети")
                
                // Имитация сетевого запроса
                Thread.sleep(200)
                
                synchronized(databaseLock) {
                    println("Сетевой поток: блокировка БД")
                    sharedList.add("Network data")
                    // Deadlock: этот поток ждет databaseLock, 
                    // которая может быть у другого потока
                }
            }
        }

        // Поток для обработки данных из БД
        thread {
            synchronized(databaseLock) {
                println("БД поток: блокировка БД")
                
                // Имитация работы с БД
                Thread.sleep(200)
                
                synchronized(networkLock) {
                    println("БД поток: блокировка сети")
                    sharedList.add("DB data")
                    // Deadlock: этот поток ждет networkLock
                }
            }
        }
    }
}

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

// Метод для проверки наличия взаимных блокировок
fun checkForDeadlocks() {
    // Мониторинг через ThreadMXBean
    val threadBean = ManagementFactory.getThreadMXBean()
    
    // Поиск deadlocked потоков
    val deadlockedThreads = threadBean.findDeadlockedThreads()
    
    if (deadlockedThreads != null && deadlockedThreads.isNotEmpty()) {
        println("Обнаружен Deadlock в потоках:")
        deadlockedThreads.forEach { threadId ->
            val threadInfo = threadBean.getThreadInfo(threadId)
            println("Поток: ${threadInfo.threadName}")
            println("Блокировка: ${threadInfo.lockName}")
            println("Владелец блокировки: ${threadInfo.lockOwnerName}")
        }
        
        // В реальном приложении здесь может быть логирование и уведомление
        FirebaseCrashlytics.getInstance().log("Deadlock detected")
    }
}

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

  1. Упорядочивание блокировок — всегда захватывать ресурсы в одинаковом порядке:
class SafeResourceManager {
    private val lock1 = Object()
    private val lock2 = Object()
    
    fun safeOperation() {
        // Всегда сначала lock1, затем lock2
        synchronized(lock1) {
            synchronized(lock2) {
                // Безопасная работа с ресурсами
            }
        }
    }
}
  1. Использование таймаутов — с помощью ReentrantLock с tryLock:
fun avoidDeadlockWithTimeout() {
    val lock1 = ReentrantLock()
    val lock2 = ReentrantLock()
    
    thread {
        if (lock1.tryLock(1, TimeUnit.SECONDS)) {
            try {
                if (lock2.tryLock(1, TimeUnit.SECONDS)) {
                    try {
                        // Критическая секция
                    } finally {
                        lock2.unlock()
                    }
                }
            } finally {
                lock1.unlock()
            }
        }
    }
}
  1. Использование атомарных операций и потокобезопасных коллекций:
class ThreadSafeExample {
    // Использование потокобезопасных коллекций из java.util.concurrent
    private val concurrentMap = ConcurrentHashMap<String, String>()
    private val atomicCounter = AtomicInteger(0)
    
    fun threadSafeIncrement() {
        atomicCounter.incrementAndGet() // Атомарная операция без блокировок
    }
}

Особенности Deadlock в Android

В Android deadlock особенно опасен, потому что может привести к:

  • ANR (Application Not Responding) — если deadlock происходит в UI потоке
  • Утечкам памяти — заблокированные потоки не могут освободить ресурсы
  • Разрядке батареи — потоки продолжают потреблять ресурсы

Для диагностики deadlock в Android используйте:

  • StrictMode для обнаружения проблем в UI потоке
  • Systrace и Perfetto для анализа блокировок
  • Логирование Thread.dumpStack() для анализа состояния потоков

Понимание механизмов возникновения и предотвращения deadlock критически важно для создания стабильных Android-приложений, особенно при работе с многопоточностью, базами данных, сетевыми запросами и асинхронными операциями.

Приведи пример DeadLock | PrepBro