> Какие проблемы с многопоточностью существуют, например race condition, data race, starvation, priority inversion, deadlock (iOS, Swift)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: Bip.ru
Стек: iOS, Swift
> Пример ответа
Короткий ответ
Основные проблемы многопоточности в iOS: race condition (непредсказуемый порядок выполнения), data race (одновременный доступ к памяти без синхронизации), starvation (поток не получает ресурсы), priority inversion (низкоприоритетный поток блокирует высокоприоритетный) и deadlock (взаимная блокировка). В Swift это решается через GCD, операционные очереди, семафоры, NSLock и акторы. На практике чаще всего встречаются data race и deadlock, особенно при работе с общими mutable-состояниями.
Подробное объяснение
Race condition - логическая ошибка, когда результат зависит от порядка выполнения потоков. Может возникать даже без data race, если операции не атомарны.
Data race - два потока одновременно обращаются к одной памяти, и хотя бы один пишет. В Swift это undefined behavior, приводит к крашам и повреждению данных. Инструменты: Thread Sanitizer, акторы.
Starvation - поток бесконечно ждёт ресурс, который другие потоки захватывают чаще. В GCD это редкость, но возможно при неправильной работе с семафорами или fair locks.
Priority inversion - низкоприоритетный поток держит lock, а высокоприоритетный ждёт. Классический пример - проблема с NSLock и QoS. Решение: os_unfair_lock с наследованием приоритета или избегание блокировок в критических секциях.
Deadlock - два потока держат ресурсы и ждут друг друга. В Swift часто возникает при вложенных sync вызовах в GCD или неправильном порядке захвата lock'ов.
Дополнительно стоит упомянуть livelock (потоки активно меняют состояние, но не прогрессируют) и false sharing (кэш-линии) - реже, но важно для senior.
На практике
В iOS-разработке основные сценарии:
- Обновление UI из фонового потока - классический race condition.
- Работа с общими моделями данных (например, кэш) без синхронизации - data race.
- Использование
DispatchSemaphoreс неправильным таймаутом - starvation. - Вложенные
queue.sync- deadlock. - Приоритеты QoS: если низкоприоритетная задача держит lock, а высокоприоритетная ждёт - priority inversion.
Практические инструменты:
- Thread Sanitizer (TSan) для детекции data race.
- Акторы в Swift 5.5+ - компилятор гарантирует изоляцию.
@MainActorдля UI-связанных операций.DispatchWorkItemс QoS для управления приоритетами.
Пример кода
SWIFT// Data race: общий mutable statefinal class Counter {var value = 0}let counter = Counter()DispatchQueue.concurrentPerform(iterations: 1000) { _ incounter.value += 1 // data race}// Решение через акторactor CounterActor {private var value = 0func increment() {value += 1}}// Deadlock: вложенный synclet queue = DispatchQueue(label: "test")queue.sync {queue.sync { // deadlockprint("never")}}// Priority inversion: низкий QoS держит locklet lock = NSLock()DispatchQueue.global(qos: .utility).async {lock.lock()sleep(1)lock.unlock()}DispatchQueue.global(qos: .userInteractive).async {lock.lock() // ждёт, пока utility завершит}
Как отвечать на собеседовании
Начни с краткого определения каждого термина, затем переходи к практическим примерам из iOS. Покажи понимание инструментов: TSan, акторы, GCD. Обязательно упомяни, что data race - это UB, а race condition - логическая ошибка. Приведи реальный кейс из своего опыта, например, как вы ловили deadlock через DispatchQueue.main.sync в замыкании. Если спросят про priority inversion - расскажи про os_unfair_lock и почему он лучше NSLock. Не углубляйся в теорию ОС, если не просят.
Что проверяет интервьюер
- Понимание различий между race condition и data race.
- Знание конкретных механизмов синхронизации в Swift/GCD.
- Умение диагностировать проблемы (TSan, Instruments).
- Опыт с акторами и async/await.
- Способность объяснить trade-off между блокировками и изоляцией.
- Понимание QoS и приоритетов.
Типичные ошибки
- Путать race condition и data race - это разные вещи.
- Говорить, что
NSLockрешает все проблемы - нет, он сам может вызвать deadlock. - Не упоминать акторы - для senior это критично.
- Предлагать
DispatchQueue.main.asyncкак универсальное решение - не всегда. - Забывать про TSan и Instruments - без них диагностика сложна.
- Утверждать, что
syncна главной очереди безопасен - это частая причина deadlock.
> Похожие задачи по mobile
Как показать пользователю, что все элементы успешно удалены
Как реализовать удаление нескольких элементов при ограничении бэкенда на один запрос на удаление
В чем разница паттернов Bridge и Proxy
Как решить проблему тестирования синглтона с использованием моков
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью