Как называется проблема с распределением ресурсов при работе двух асинхронных очередей
Что проверяют
Различаете ли вы проблемы конкурентности по симптомам, а не называете всё «гонкой». Формулировка размытая, поэтому сильный ответ начинается с уточнения сценария. Следом обычно просят показать, как вы нашли бы такую проблему и чем исправили бы.
Как отвечать
Назовите кандидатов и признаки каждого:
- race condition (data race): две очереди без синхронизации читают и пишут общий ресурс, например массив. Итог зависит от порядка выполнения, падения случайные. Ловится Thread Sanitizer в схеме Xcode;
- deadlock: очереди ждут друг друга. Классика: очередь A делает
syncна B, а B в это времяsyncна A, или вызовDispatchQueue.main.syncиз главного потока; - priority inversion: задача с низким QoS держит ресурс, а задача с высоким ждёт. GCD умеет поднимать приоритет, когда ожидание идёт через
syncна последовательную очередь, но не черезDispatchSemaphore: семафор не знает, кто его освободит; - starvation и thread explosion: одна очередь так и не получает ресурс, или сотни блокирующих задач на concurrent-очереди плодят потоки.
Если спрашивают именно про «распределение ресурсов между очередями», чаще всего ждут priority inversion или deadlock, и стоит сказать это прямо.
Исправления: последовательная очередь как единственный владелец ресурса, concurrent-очередь с флагом .barrier для схемы «много читателей, один писатель», os_unfair_lock или Mutex из фреймворка Synchronization на iOS 18 и новее, в Swift Concurrency actor. В Swift 6 строгая проверка Sendable ловит многие гонки ещё при компиляции.
Где спотыкаются
Называют race condition на любой вопрос о многопоточности. Если ресурсы захвачены по кругу, приложение не падает, а зависает, и это другая проблема с другим лечением.
Лечат гонку семафором и получают инверсию приоритетов. Xcode может подсказать это предупреждением Thread Performance Checker, но лучше не доводить.
Считают actor полной защитой. Он сериализует доступ, но на каждом await внутри метода состояние может измениться, это reentrancy, и проверку после await нужно повторять.