Ответ
Взаимная блокировка (Deadlock) — это ситуация, когда два или более потока находятся в состоянии бесконечного ожидания ресурсов, захваченных друг другом.
Условия возникновения (Условия Коффмана):
- Взаимное исключение: Ресурс не может быть использован несколькими потоками одновременно.
- Удержание и ожидание: Поток удерживает один ресурс и ждет другой.
- Отсутствие вытеснения: Ресурс нельзя отнять у потока.
- Циклическое ожидание: Возникает круговая зависимость потоков по ресурсам.
Классический пример на Swift (с NSLock):
let lockA = NSLock()
let lockB = NSLock()
DispatchQueue.global().async {
lockA.lock() // Поток 1 захватывает lockA
sleep(1) // Имитация работы
lockB.lock() // Поток 1 ЖДЁТ lockB (но его держит Поток 2)
// Критическая секция...
lockB.unlock()
lockA.unlock()
}
DispatchQueue.global().async {
lockB.lock() // Поток 2 захватывает lockB
sleep(1) // Имитация работы
lockA.lock() // Поток 2 ЖДЁТ lockA (но его держит Поток 1)
// Критическая секция...
lockA.unlock()
lockB.unlock()
}
// Оба потока заблокированы навсегда.
Способы предотвращения:
- Упорядочивание блокировок: Всегда захватывать ресурсы в одинаковом глобальном порядке (сначала A, потом B).
- Использование
NSLock.try()или блокировок с таймаутом. - Отказ от явных блокировок в пользу высокоуровневых механизмов GCD (очереди,
DispatchSemaphore,DispatchGroup). - Проектирование без состояний или с использованием потокобезопасных структур данных.