Гарантирует ли async/await в Swift потокобезопасность?

«Гарантирует ли async/await в Swift потокобезопасность?» — вопрос из категории Многопоточность, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, сам по себе async/await не гарантирует потокобезопасность. Он решает проблему "ада обратных вызовов" (callback hell), упрощая написание и чтение асинхронного кода, но не защищает от состояний гонки (race conditions) и других проблем параллельного доступа к данным.

async лишь указывает, что функция может приостановить выполнение, а await — точка приостановки. Код внутри async-функции может выполняться на разных потоках.

Для обеспечения потокобезопасности в контексте async/await необходимо использовать дополнительные механизмы:

  1. @MainActor: Для изоляции кода, работающего с UI, на главном потоке.
    @MainActor func updateUI() { ... }
  2. Actors: Специальный тип, который изолирует свои свойства и методы, обеспечивая безопасный доступ из разных задач.
    actor Counter {
        private var value = 0
        func increment() { value += 1 }
        func getValue() -> Int { return value }
    }
    // Доступ только через `await`
    let counter = Counter()
    await counter.increment()
  3. Классические примитивы синхронизации: DispatchQueue (с барьерами), NSLock, os_unfair_lock, семафоры — для защиты общих ресурсов вне акторов.