Какие проблемы возникают с многопоточностью, например deadlock, race condition, starvation, priority inversion
Что проверяют
Различаете ли вы эти состояния и знаете ли, как каждое проявляется и лечится в iOS.
Как отвечать
Состояние гонки (race condition): результат зависит от порядка выполнения потоков. Частный случай, гонка за данными (data race), это одновременный доступ к одной памяти без синхронизации, где хотя бы один поток пишет. Проявляется плавающими падениями и порчей данных. Ловится Thread Sanitizer.
Взаимная блокировка (deadlock): потоки ждут ресурсы друг друга. Самый частый случай в iOS это не два мьютекса, а DispatchQueue.main.sync из главного потока или sync на текущую последовательную очередь: очередь ждёт саму себя и виснет намертво.
Голодание (starvation): поток формально может продолжить, но никогда не получает ресурс, потому что его перехватывают другие. Возникает при большом числе высокоприоритетных задач или при постоянном потоке читателей, не пускающем писателя.
Инверсия приоритетов (priority inversion): низкоприоритетный поток держит ресурс, нужный высокоприоритетному, а среднеприоритетные вытесняют низкоприоритетный, и высокий ждёт неопределённо долго. Именно поэтому OSSpinLock признан небезопасным и объявлен устаревшим: он крутится в цикле и усугубляет проблему. GCD с этим борется через передачу приоритета: очередь временно поднимает класс обслуживания того, кого ждут.
Инструменты и решения:
- Thread Sanitizer и Main Thread Checker в схеме сборки, оба ловят реальные ошибки, которые иначе плавают;
- последовательная очередь как замена блокировке, барьер для схемы «много читателей, один писатель»;
- актор в Swift Concurrency изолирует состояние по построению, а строгая проверка конкурентности и
Sendableпереносят часть ошибок с рантайма на компиляцию; - единый порядок захвата блокировок там, где они всё-таки нужны.
Где спотыкаются
Путают гонку и взаимную блокировку.
Пишут DispatchQueue.main.sync и получают зависание.
Не знают про инверсию приоритетов и продолжают использовать спин-блокировки.
Считают, что свойство с атрибутом atomic делает код потокобезопасным.