Как устроена многопоточность в GCD, какие бывают очереди и способы отправки задач
GCDiOS разработкаасинхронностьмногопоточностьочереди
Что проверяют
Понимаете ли вы, что вы управляете очередями, а не потоками, и знаете ли, чем sync опасен.
Как отвечать
GCD это очереди задач и пул потоков под ними. Вы кладёте замыкание в очередь, а решение о том, на каком потоке его выполнить, принимает система.
Виды очередей:
- главная (
DispatchQueue.main): последовательная, привязана к потоку интерфейса. Всё, что трогает UIKit или SwiftUI, только отсюда; - глобальные конкурентные с уровнем качества обслуживания:
.userInteractive,.userInitiated,.utility,.background. Уровень это подсказка планировщику о приоритете и энергопотреблении; - свои: по умолчанию последовательные (
DispatchQueue(label:)), либо конкурентные сattributes: .concurrent.
Способы отправки:
async: положить и вернуться немедленно. Основной вариант;sync: положить и ждать завершения. Опасен:syncна текущую последовательную очередь это мгновенная взаимная блокировка, аsyncна главную из главного потока роняет приложение;asyncAfterдля задержки,concurrentPerformдля параллельного цикла,DispatchGroupдля ожидания нескольких задач,DispatchSemaphoreдля ограничения одновременных операций;- барьер (
flags: .barrier) в своей конкурентной очереди даёт схему «много читателей, один писатель».
Стоит добавить, что в новом коде вместо GCD берут Swift Concurrency (async/await, акторы): там изоляция состояния проверяется компилятором, а не дисциплиной.
Где спотыкаются
Путают очередь и поток, считая, что последовательная очередь это выделенный поток.
Вызывают sync на главную очередь из главного потока.
Обновляют интерфейс из фоновой очереди.
Плодят семафоры вместо использования групп и барьеров.