Ответ вслух Middle GCD и OperationQueue обновлено

Взаимные блокировки в GCD

Вопрос

Какие взаимные блокировки бывают в GCD и как их избежать?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Самый частый deadlock: sync на ту же последовательную очередь, в которой ты уже находишься. Например, DispatchQueue.main.sync с главного потока или вложенный queue.sync внутри блока этой же очереди.

Что должно прозвучать в ответе

  • `sync` на текущую serial-очередь (в том числе `main.sync` с главного)

  • Две serial-очереди делают `sync` друг на друга

  • `group.wait()` или `semaphore.wait()` на главном потоке, когда завершение тоже нужно главному

  • Исчерпание потоков при массовой блокировке

  • Профилактика: `async` по умолчанию, не держать блокировки при вызове внешнего кода, Swift Concurrency

Что могут спросить следом

  • Как понять, что ты уже на нужной очереди?
  • Чем dispatchPrecondition помогает в отладке?

Разбор

Самый частый deadlock: sync на ту же последовательную очередь, в которой ты уже находишься. Например, DispatchQueue.main.sync с главного потока или вложенный queue.sync внутри блока этой же очереди. Вариант посложнее: очередь A делает sync на B, а B в это время sync на A. Ещё сценарий: на главном потоке group.wait(), а completion сетевого запроса тоже хочет выполниться на главной очереди. И отдельная беда: сотни блокирующих задач исчерпывают пул потоков, и очереди стоят. Избегаю так: по умолчанию async, sync только на свою приватную очередь и только снаружи неё, dispatchPrecondition(condition: .onQueue(q)) в отладке, чтобы ловить вызовы не с той очереди. А новый код пишу на async/await, где компилятор не даст заблокировать актор так просто.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме