Почему вызов DispatchQueue.main.sync из главного потока приводит к deadlock?

«Почему вызов DispatchQueue.main.sync из главного потока приводит к deadlock?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Вызов DispatchQueue.main.sync из того же самого (главного) потока вызывает взаимную блокировку (deadlock) из-за принципа работы синхронных операций и очередей.

Механизм deadlock:

  1. sync блокирует текущий поток и ждет, пока переданный блок кода выполнится.
  2. Блок кода ставится в очередь (DispatchQueue.main) на выполнение.
  3. Если очередь уже занята этим же потоком (главный поток выполняет наш sync-вызов), она не может начать выполнение нового блока, пока не освободится.
  4. Возникает циклическая зависимость: Поток ждет очередь → Очередь ждет поток.

Пример deadlock:

// Вызов из главного потока:
DispatchQueue.main.sync {
    // Этот блок никогда не будет выполнен
    updateUI()
}
// Поток заблокирован здесь навсегда

Решение: Всегда используйте DispatchQueue.main.async для планирования работы на главной очереди из самого главного потока.

// Правильно:
DispatchQueue.main.async {
    self.updateUI()
}

Исключение: Вызов sync из другого (фонового) потока на главную очередь — безопасен и является стандартным паттерном для синхронизации результатов с UI.