В чем разница между семафором и барьером?
Что проверяют
Знаете ли вы примитивы синхронизации GCD и понимаете ли, от какой проблемы спасает каждый. В iOS «барьер» почти всегда означает флаг .barrier у задачи на конкурентной очереди, а не классический барьер из учебника по многопоточности. Следом часто просят написать потокобезопасное хранилище или спрашивают, чем это заменить в Swift Concurrency.
Как отвечать
DispatchSemaphore: счётчик с операциямиwait()иsignal().wait()уменьшает счётчик и блокирует поток, если значение ушло ниже нуля;signal()увеличивает его и будит ждущего. Семафор с начальным значением3ограничивает, например, число одновременных загрузок, с0превращает асинхронный вызов в синхронное ожидание;- барьер (
queue.async(flags: .barrier)): задача на собственной конкурентной очереди, которая ждёт завершения всех ранее поставленных задач, выполняется одна и только потом пускает следующие. Классическое применение: паттерн «читатели и писатель», где чтение идёт черезsyncпараллельно, а запись через барьер эксклюзивно.
Разница в сути: семафор ограничивает количество одновременных участников и ничего не знает об очереди, барьер привязан к конкретной очереди и даёт эксклюзивное окно для записи. Если интервьюер имеет в виду классический барьер «все ждут всех», его аналог в GCD это DispatchGroup с notify или wait.
В Swift Concurrency оба инструмента заменяются: общее изменяемое состояние прячут в actor, а ограничение параллелизма делают через TaskGroup, контролируя число запущенных задач.
Где спотыкаются
Ставят барьер на DispatchQueue.global(). Там флаг игнорируется, и задача выполняется как обычная, без всякой эксклюзивности. Барьер работает только на своей очереди с атрибутом .concurrent.
Вызывают semaphore.wait() на главном потоке в ожидании ответа сети. Интерфейс замерзает, а если колбэк приходит на главную очередь, получается взаимная блокировка.
Используют семафоры внутри async-функций. Блокировка потока из кооперативного пула Swift Concurrency нарушает его контракт и может подвесить приложение; к тому же семафор не передаёт приоритет, и возникает инверсия приоритетов.