Могут ли несколько потоков одновременно изменять один объект в Swift?

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

Ответ

Да, могут, но это приводит к состоянию гонки (race condition) и неопределенному поведению, если доступ не синхронизирован. Параллельная запись может повредить данные.

Пример проблемы (гонка данных):

var counter = 0
DispatchQueue.concurrentPerform(iterations: 100) { _ in
    counter += 1 // Небезопасно: несколько потоков читают и пишут одновременно
}
print(counter) // Результат может быть меньше 100

Решение — использование механизмов синхронизации:

  • DispatchQueue с барьером (barrier) или синхронным доступом (sync) для сериализации операций записи.
  • NSLock / os_unfair_lock для явной блокировки.
  • @MainActor для безопасного обновления UI из разных потоков.
  • Actor (Swift 5.5+) — современный тип, обеспечивающий изоляцию.

Пример с Actor:

actor SafeCounter {
    private var value = 0
    func increment() { value += 1 }
    func getValue() -> Int { value }
}

// Использование:
let counter = SafeCounter()
Task {
    await counter.increment() // Доступ изолирован, гонок нет
}