Что произойдет, если вызвать sync на serial очереди (GCD)?

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

Ответ

Вызов sync на serial (последовательной) очереди может привести к взаимной блокировке (deadlock), если этот вызов выполняется из той же самой очереди.

Причина deadlock:

  1. Метод sync блокирует текущий поток до полного выполнения переданного блока кода.
  2. Serial очередь выполняет задачи строго по одной.
  3. Если очередь уже выполняет какую-то внешнюю задачу (например, из предыдущего async), она не может начать новую задачу (блок из sync), так как занята.
  4. Внешняя задача, в свою очередь, ждет завершения sync, создавая циклическую зависимость.

Пример deadlock:

let serialQueue = DispatchQueue(label: "com.example.serial")

serialQueue.async { // Задача A начинает выполняться на очереди
    // Пока выполняется эта задача A, мы пытаемся отправить sync...
    serialQueue.sync { // Задача B: DEADLOCK! Очередь не может начать B, пока не завершит A.
        print("Этот код никогда не выполнится")
    }
}

Как избежать:

  • Не вызывайте DispatchQueue.sync из той же serial очереди, на которую вы его отправляете.
  • Используйте async для фоновых задач или отправляйте sync на другую очередь.
  • Для concurrent (параллельных) очередей такой проблемы нет.