Что произойдёт при вызове DispatchQueue.main.sync из главного потока в iOS?

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

Ответ

Вызов DispatchQueue.main.sync из главного потока приведёт к deadlock (взаимной блокировке).

Причина: Главный поток пытается выполнить блок синхронно, но очередь main уже занята этим же потоком, который ожидает завершения блока. Возникает циклическая зависимость.

Пример deadlock:

// Вызов в AppDelegate или ViewController на главном потоке
func viewDidLoad() {
    super.viewDidLoad()

    DispatchQueue.main.sync {
        // Этот код никогда не выполнится
        print("Deadlock!")
    }
    // Сюда управление не вернётся
}

Решение:

  1. Используйте async вместо sync для главного потока:

    DispatchQueue.main.async {
    // Обновление UI
    self.label.text = "Updated"
    }
  2. Проверяйте текущую очередь перед вызовом sync:

    if Thread.isMainThread {
    // Выполняем код напрямую
    updateUI()
    } else {
    DispatchQueue.main.sync {
        updateUI()
    }
    }
  3. Используйте DispatchQueue.main.async по умолчанию для всех операций с UI.

Важно: DispatchQueue.main.sync можно безопасно использовать только из фонового потока, когда нужно дождаться обновления UI перед продолжением работы.