← Назад к вопросам
Приведи пример DeadLock
2.7 Senior🔥 102 комментариев
#Многопоточность и асинхронность
Комментарии (2)
🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Пример Deadlock в Android/Java
Deadlock (взаимная блокировка) — это ситуация в многопоточном программировании, когда два или более потока **бесконечно ожидают** ресурсы, захваченные друг другом, что приводит к полной остановке выполнения.
Ключевые условия возникновения Deadlock
Для возникновения взаимной блокировки необходимо одновременное выполнение четырех условий (условия Коффмана):
- Взаимное исключение — ресурс не может использоваться несколькими потоками одновременно
- Удержание и ожидание — поток удерживает один ресурс и ждет другой
- Отсутствие вытеснения — ресурс нельзя отнять у потока
- Круговая зависимость — циклическая цепочка ожидающих потоков
Практический пример 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
- Упорядочивание блокировок — всегда захватывать ресурсы в одинаковом порядке:
class SafeResourceManager {
private val lock1 = Object()
private val lock2 = Object()
fun safeOperation() {
// Всегда сначала lock1, затем lock2
synchronized(lock1) {
synchronized(lock2) {
// Безопасная работа с ресурсами
}
}
}
}
- Использование таймаутов — с помощью
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()
}
}
}
}
- Использование атомарных операций и потокобезопасных коллекций:
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-приложений, особенно при работе с многопоточностью, базами данных, сетевыми запросами и асинхронными операциями.