> Что происходит при дедлоке в главной очереди в iOS (iOS, Swift)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: Совкомбанк
Стек: iOS, Swift
> Пример ответа
Короткий ответ
Дедлок в главной очереди - это ситуация, когда main queue заблокирована ожиданием ресурса, который никогда не будет освобождён, потому что освобождение должно произойти в той же очереди. UI перестаёт реагировать на события, приложение выглядит зависшим. Чаще всего возникает при синхронном вызове DispatchQueue.main.sync из самой main queue или при неправильной работе с семафорами и блокировками.
Подробное объяснение
Главная очередь - это serial queue, которая выполняет задачи последовательно. Дедлок возникает, когда задача, выполняющаяся в main queue, синхронно ожидает завершения другой задачи, которая должна быть поставлена в ту же очередь. Поскольку очередь занята текущей задачей, новая задача не может начаться, и обе задачи ждут друг друга бесконечно.
Основные сценарии:
-
DispatchQueue.main.syncиз main queue - классический случай. Вызовsyncблокирует текущий поток до завершения переданного блока, но блок не может выполниться, потому что очередь занята. -
Взаимная блокировка через семафоры - если в main queue вызывается
semaphore.wait(), а сигналsemaphore.signal()должен быть отправлен из задачи, поставленной в ту же очередь. -
Блокировки (NSLock, NSRecursiveLock) - если поток main queue пытается захватить lock, который уже удерживается другой задачей в той же очереди, и эта задача не может завершиться.
-
Вложенные sync-вызовы - когда внутри блока, выполняющегося в main queue, вызывается
syncна другую serial queue, которая в свою очередь делаетsyncобратно на main queue.
Важно понимать, что дедлок в main queue не всегда приводит к крашу - приложение просто перестаёт отвечать. Система может убить процесс через некоторое время (watchdog), но обычно это выглядит как зависание.
На практике
На практике дедлоки в main queue чаще всего встречаются в legacy-коде, где разработчики не осознают, что уже находятся в main queue. Типичные ситуации:
- Вызов
DispatchQueue.main.syncвнутриviewDidLoad,viewWillAppearили обработчиков UI-событий. - Использование
semaphore.wait()в main queue для ожидания завершения сетевого запроса или фоновой задачи. - Неправильная работа с
DispatchGroup- вызовgroup.wait()в main queue, пока задачи группы ещё не завершены.
Правильный подход - всегда проверять, находитесь ли вы в main queue, и использовать асинхронные паттерны (completion handlers, async/await, Combine) вместо синхронного ожидания.
Пример кода
SWIFT// Классический дедлокDispatchQueue.main.sync {// Этот блок никогда не выполнитсяprint("Deadlock")}// Дедлок через семафорlet semaphore = DispatchSemaphore(value: 0)DispatchQueue.main.async {semaphore.wait() // Блокирует main queue// Код ниже не выполнится}semaphore.signal() // Этот вызов не выполнится, пока main queue заблокирована// Правильный подход - асинхронное выполнениеDispatchQueue.main.async {// Работа с UI}
Как отвечать на собеседовании
Начните с чёткого определения дедлока и его причины - блокировка main queue при синхронном ожидании задачи из той же очереди. Объясните, почему это происходит: serial queue не может выполнить новую задачу, пока текущая не завершена. Приведите конкретные примеры из практики, покажите понимание последствий - зависание UI, срабатывание watchdog. Обязательно упомяните способы диагностики: использование DispatchQueue.main проверки через Thread.isMainThread, инструменты типа Instruments (Time Profiler, Thread Sanitizer). Завершите рассказом о правильных паттернах - async/await, completion handlers, избегание sync-вызовов на main queue.
Что проверяет интервьюер
Интервьюер оценивает:
- Понимание модели выполнения GCD и serial queues.
- Умение объяснить, почему возникает взаимная блокировка.
- Знание конкретных сценариев, приводящих к дедлоку.
- Способность предложить корректные решения и альтернативы.
- Понимание разницы между sync и async вызовами.
- Наличие практического опыта диагностики подобных проблем.
Типичные ошибки
- Утверждение, что дедлок в main queue приводит к крашу - на самом деле это зависание.
- Предложение использовать
DispatchQueue.main.asyncкак универсальное решение - это не всегда корректно, если нужно дождаться результата. - Непонимание разницы между
syncиasyncпри работе с main queue. - Игнорирование проблемы с семафорами и блокировками - многие кандидаты знают только про
main.sync. - Отсутствие упоминания современных подходов (async/await, Combine) как альтернативы синхронному ожиданию.
> Похожие задачи по mobile
Как работает таймер в iOS и с чем связана его работа
Что происходит с таймером, если он запущен в глобальной очереди, а не в главной в iOS
Какие альтернативы NSOperation существуют для отслеживания выполнения задач в iOS
Как показать пользователю, что все элементы успешно удалены
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью