Какой основной риск при использовании `sync` в GCD (Grand Central Dispatch)?

«Какой основной риск при использовании `sync` в GCD (Grand Central Dispatch)?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Основной риск — взаимная блокировка (deadlock), если вызвать sync на текущей последовательной (serial) очереди. Это происходит потому, что sync блокирует текущий поток до завершения переданного блока, который никогда не начнет выполняться, если очередь занята ожиданием.

Классический опасный пример на главном потоке:

// Вызов из main thread приведет к deadlock
DispatchQueue.main.sync {
    print("Этот код никогда не выполнится.")
}

Почему это происходит: DispatchQueue.main — последовательная очередь. Вызов sync из main thread блокирует его, ожидая выполнения блока. Но этот блок может начать выполняться только тогда, когда main thread освободится, что создает циклическую зависимость.

Best practices:

  1. Избегайте sync на main queue из main thread.
  2. Проверяйте текущую очередь перед вызовом sync.
  3. Предпочитайте async для всех операций, не требующих немедленного синхронного результата, особенно в UI-коде.
  4. Для безопасного выполнения кода на текущей очереди используйте проверку:
    if DispatchQueue.isCurrentQueueSerial {
    // Выполняем блок напрямую или используем async
    block()
    } else {
    queue.sync { block() }
    }

    Используйте sync осознанно, только когда необходимо дождаться результата, и вы уверены в отсутствии конфликта очередей.