Какие механизмы синхронизации существуют для решения проблем многопоточности
Что проверяют
Знаете ли вы примитивы и, что важнее, понимаете ли, какой уместен в конкретной ситуации. Вопрос почти всегда ведёт к разговору про гонку данных: как вы её обнаруживали и чем чинили. Следом спрашивают, как то же самое выглядит в Swift Concurrency и что изменилось с переходом на строгую проверку конкурентности.
Как отвечать
Разделите ответ на классический слой и современный.
- последовательная очередь:
DispatchQueueбез флага.concurrentсериализует доступ и часто дешевле явного замка; - замки:
NSLock,NSRecursiveLock, быстрыйos_unfair_lock(не рекурсивный и не переносимый копированием структуры),Mutexиз фреймворка Synchronization начиная с iOS 18; - семафор:
DispatchSemaphoreограничивает число одновременных операций, например четыре параллельные загрузки; - барьер:
queue.async(flags: .barrier)на конкурентной очереди даёт схему «много читателей, один писатель»; OperationQueue: зависимости между задачами, отмена,maxConcurrentOperationCount;- акторы:
actorизолирует своё состояние, обращение снаружи идёт черезawait,@MainActorзакрепляет работу с интерфейсом за главным потоком; Sendable: в языковом режиме Swift 6 компилятор проверяет передачу значений между изолированными контекстами, и часть гонок превращается в ошибку сборки.
Обязательно упомяните реентерантность акторов: между двумя await состояние могло измениться, поэтому актор защищает от гонки данных, но не от логической гонки. И назовите инструменты диагностики: Thread Sanitizer и Main Thread Checker в схеме проекта.
Где спотыкаются
Считают, что DispatchQueue.main.async решает проблему. Он лишь переносит выполнение на главный поток, а если запись идёт ещё и из фоновых, гонка остаётся на месте.
Смешивают семафоры с async и await. Вызов wait() внутри задачи блокирует поток кооперативного пула, а пул этот небольшой, отсюда зависания и дедлоки на ровном месте.
Объявляют @MainActor всему подряд и получают подтормаживания интерфейса. Обратная крайность тоже встречается: считают, что актор снимает все вопросы, и выносят из него ссылочный объект, снова делая состояние общим.