> Что делает dispatch_sync в GCD? (iOS, Swift)

Уровень: senior · Роль: mobile · Категория: Технические вопросы

Компании: Московская биржа, VK, Яндекс

Стек: iOS, Swift

> Пример ответа

Короткий ответ

dispatch_sync - это функция Grand Central Dispatch, которая синхронно отправляет блок или замыкание в указанную очередь и блокирует текущий поток до завершения его выполнения. В отличие от dispatch_async, она не возвращает управление, пока задача не будет полностью выполнена. Используется для синхронизации доступа к общим ресурсам или для ожидания результата работы другой очереди, но требует осторожности из-за риска deadlock при вызове на главной очереди или из той же очереди.

Подробное объяснение

dispatch_sync - часть C-интерфейса GCD, в Swift доступна как DispatchQueue.sync. Основное поведение:

  • блокирует вызывающий поток до завершения переданного замыкания;
  • замыкание выполняется на целевой очереди, но вызывающий поток ждёт;
  • если очередь серийная и текущий поток уже выполняет задачу на ней - возникает deadlock, так как очередь не может запустить новую задачу, пока текущая не завершится, а текущая ждёт завершения новой.

Ключевые сценарии использования:

  • синхронное обновление UI из фоновой очереди - отправка блока на main queue;
  • защита общего ресурса через серийную очередь вместо lock;
  • ожидание завершения группы задач перед продолжением.

Важные нюансы:

  • на concurrent queue dispatch_sync не создаёт deadlock, если вызывается не из той же очереди, но всё равно блокирует поток;
  • вызов sync на главной очереди из главного потока - гарантированный deadlock;
  • sync на серийной очереди из той же очереди - deadlock;
  • для обратной совместимости с ObjC-кодом используется dispatch_sync, в Swift - метод sync на DispatchQueue.

На практике

В реальном коде dispatch_sync встречается реже, чем async, потому что блокировка потока - дорогая операция и источник ошибок. Основные практические применения:

  • обновление UI: DispatchQueue.main.sync из фонового потока, когда нужно гарантировать, что UI обновлён до продолжения работы (например, при snapshot);
  • синхронизация доступа к mutable state через серийную очередь - альтернатива NSLock или @synchronized;
  • ожидание завершения операции в тестах или при инициализации.

Частая замена - async + DispatchGroup или semaphore, если нужно дождаться результата, не блокируя поток. На практике для синхронизации данных чаще используют DispatchQueue.async с барьером (barrier), а sync - только для коротких критических секций.

Пример кода

SWIFT
// Серийная очередь для защиты ресурса
private let queue = DispatchQueue(label: "com.example.sync")
private var _value: Int = 0
var value: Int {
get { queue.sync { _value } }
set { queue.sync { _value = newValue } }
}
// Синхронное обновление UI из фоновой очереди
DispatchQueue.global().async {
let result = heavyComputation()
DispatchQueue.main.sync {
self.label.text = result
}
}
// Опасный пример - deadlock
DispatchQueue.main.sync { // вызывается из main thread
// никогда не выполнится
}

Как отвечать на собеседовании

Начни с точного определения: синхронная отправка, блокировка вызывающего потока. Затем приведи пример использования и обязательно упомяни deadlock - это ключевой момент, который проверяет понимание. Расскажи про разницу между серийной и concurrent очередью в контексте sync. Если спросят про альтернативы - назови async + DispatchGroup, semaphore, barrier. Покажи, что понимаешь, когда sync оправдан, а когда лучше избегать. Хорошо добавить сравнение с async по стоимости и поведению.

Что проверяет интервьюер

  • понимание модели выполнения GCD: очереди, потоки, блокировка;
  • знание последствий блокировки потока и риска deadlock;
  • умение выбрать правильный инструмент для синхронизации;
  • знание Swift API (DispatchQueue.sync) и C-функции dispatch_sync;
  • способность объяснить разницу между sync и async на конкретных примерах.

Типичные ошибки

  • утверждение, что sync выполняется в текущем потоке - это неверно, он выполняется на целевой очереди, но блокирует текущий;
  • игнорирование deadlock при вызове на main queue из main thread;
  • использование sync для длительных операций - блокирует поток без необходимости;
  • путаница между sync и async при работе с concurrent queue;
  • забывание, что sync на серийной очереди из той же очереди - deadlock, даже если очередь не main.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью