Являются ли классы в Swift потокобезопасными по умолчанию?

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

Ответ

Нет. Классы в Swift (как и в большинстве языков) не являются потокобезопасными по умолчанию.

Экземпляр класса — это разделяемый изменяемый ресурс. Если несколько потоков одновременно обращаются к одному экземпляру и хотя бы один поток выполняет запись, возникает гонка данных (race condition). Это приводит к неопределённому поведению, сбоям (EXC_BAD_ACCESS) или повреждению данных.

Пример проблемы:

class UnsafeCounter {
    var value = 0
    func increment() { value += 1 } // НЕ атомарная операция!
}

let counter = UnsafeCounter()
DispatchQueue.concurrentPerform(iterations: 1000) { _ in
    counter.increment() // ❌ Множественные потоки — гонка данных.
}
print(counter.value) // Результат непредсказуем, меньше 1000.

Способы обеспечения потокобезопасности:

  1. Изоляция через очередь (DispatchQueue):

    class ThreadSafeCounter {
        private var count = 0
        private let queue = DispatchQueue(label: "sync.queue", attributes: .concurrent)
    
        func increment() {
            queue.async(flags: .barrier) { // Барьер для записи
                self.count += 1
            }
        }
    
        var currentValue: Int {
            queue.sync { // Безопасное чтение
                return count
            }
        }
    }
  2. Акторы (actor, Swift 5.5+): Автоматическая изоляция состояния.
  3. Примитивы синхронизации: NSLock, os_unfair_lock, семафоры.
  4. Атомарные операции: Использование Atomic property wrappers или низкоуровневых функций (OSAtomic).