> Какие проблемы с многопоточностью существуют, например 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 state
final class Counter {
var value = 0
}
let counter = Counter()
DispatchQueue.concurrentPerform(iterations: 1000) { _ in
counter.value += 1 // data race
}
// Решение через актор
actor CounterActor {
private var value = 0
func increment() {
value += 1
}
}
// Deadlock: вложенный sync
let queue = DispatchQueue(label: "test")
queue.sync {
queue.sync { // deadlock
print("never")
}
}
// Priority inversion: низкий QoS держит lock
let 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.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью