В чем разница последовательной и параллельной очереди
Что проверяют
Понимаете ли вы GCD на практике: что гарантирует очередь, чем это отличается от sync и async и откуда берутся дедлоки. Следом обычно дают кусок кода с вложенными вызовами и просят назвать порядок вывода.
Как отвечать
Тип очереди отвечает на вопрос, сколько задач из неё может выполняться одновременно:
- последовательная (serial): одна задача за раз, строго в порядке добавления.
DispatchQueue(label:)создаёт именно такую, главная очередьDispatchQueue.mainтоже последовательная; - параллельная (concurrent): задачи стартуют в порядке добавления, но выполняются одновременно и завершаются в любом порядке. Своя создаётся с
attributes: .concurrent, глобальные очередиDispatchQueue.global(qos:)параллельные.
Отдельно проговорите, что sync и async это другое измерение: они определяют, ждёт ли вызывающий код окончания задачи. Поэтому встречаются все четыре комбинации.
Последовательная очередь не означает один поток. GCD берёт потоки из пула, соседние задачи могут выполниться на разных потоках, гарантируется только отсутствие одновременности. Благодаря этому такая очередь работает как замок для общего состояния.
Типичный приём с параллельной очередью: чтение идёт через sync, а запись через async(flags: .barrier). Барьер ждёт завершения текущих задач и выполняется в одиночку. Работает он только на своей параллельной очереди, на глобальной барьер ведёт себя как обычный async.
Хорошо закончить современным вариантом: в Swift Concurrency роль последовательной очереди для защиты состояния играет actor, а @MainActor заменяет ручную отправку на главную очередь.
Где спотыкаются
Вызывают sync на той же последовательной очереди, в которой уже находятся. Самый частый случай: DispatchQueue.main.sync с главного потока, и приложение падает на дедлоке.
Путают параллельную очередь с асинхронным вызовом и говорят, что async на последовательной очереди выполнит задачи одновременно.
Кидают сотни блокирующих задач в глобальную очередь. GCD создаёт новые потоки взамен заблокированных, начинается thread explosion, растут расход памяти и число переключений контекста.