> Что такое атомарная операция (iOS, Swift)

Уровень: junior · Роль: mobile · Категория: Технические вопросы

Компании: Doubletapp

Стек: iOS, Swift

> Пример ответа

Короткий ответ

Атомарная операция - это операция, которая выполняется целиком и неделимо: либо полностью завершается, либо не выполняется вовсе. В многопоточной среде это гарантирует, что другие потоки не увидят промежуточное состояние данных. В iOS и Swift атомарность важна для безопасной работы с общими ресурсами без блокировок, например, через OSAtomic или NSLock.

Подробное объяснение

Атомарность - фундаментальное понятие конкурентности. Она защищает от data race, когда несколько потоков одновременно читают и пишут одну переменную. Без атомарности возможны гонки: поток A начинает изменение, поток B читает "полуобновлённое" значение - результат непредсказуем.

В Swift атомарность не встроена в язык напрямую. Примитивы вроде Int не атомарны по умолчанию. Для атомарных операций используются:

  • OSAtomic функции (устарели, но встречаются в legacy-коде)
  • NSLock, NSRecursiveLock - классические блокировки
  • DispatchQueue с барьерами - популярный паттерн в iOS
  • os_unfair_lock - низкоуровневый быстрый lock
  • Atomic свойства через ManagedAtomic из Swift Atomics (Swift 5.5+)

Важно различать атомарность и потокобезопасность. Атомарная операция - это один шаг, а потокобезопасность - более широкое понятие, включающее согласованность состояния объекта в целом.

На практике

В iOS-разработке атомарность чаще всего нужна для:

  • счётчиков и флагов (например, количество загрузок)
  • кэшей и словарей, к которым обращаются из разных потоков
  • состояния UI-компонентов, обновляемых из фоновых потоков

Типичный паттерн - DispatchQueue с барьером:

SWIFT
final class ThreadSafeCache<Key: Hashable, Value> {
private var storage: [Key: Value] = [:]
private let queue = DispatchQueue(label: "cache.queue", attributes: .concurrent)
func value(for key: Key) -> Value? {
queue.sync { storage[key] }
}
func set(_ value: Value, for key: Key) {
queue.async(flags: .barrier) { self.storage[key] = value }
}
}

Здесь чтение идёт конкурентно, а запись - через барьер, что гарантирует атомарность изменения словаря.

Пример кода

Атомарный счётчик через os_unfair_lock:

SWIFT
import os
final class AtomicCounter {
private var lock = os_unfair_lock()
private var _value = 0
var value: Int {
os_unfair_lock_lock(&lock)
defer { os_unfair_lock_unlock(&lock) }
return _value
}
func increment() {
os_unfair_lock_lock(&lock)
defer { os_unfair_lock_unlock(&lock) }
_value += 1
}
}

Как отвечать на собеседовании

Начни с определения: "атомарная операция - неделимая, выполняется целиком". Затем приведи пример из iOS: гонка данных при инкременте счётчика из двух потоков. Объясни, почему Int не атомарен в Swift. Упомяни инструменты: NSLock, DispatchQueue с барьером, os_unfair_lock. Если спросят про atomic в Objective-C - скажи, что это свойство, но в Swift такого нет, и это не панацея от всех гонок.

Что проверяет интервьюер

  • понимание базовых принципов конкурентности
  • знание конкретных инструментов в iOS
  • умение объяснить разницу между атомарностью и потокобезопасностью
  • способность привести практический пример и обосновать выбор подхода

Типичные ошибки

  • утверждение, что Int в Swift атомарен по умолчанию
  • смешивание атомарности и @atomic из Objective-C (это про свойства, а не про операции)
  • игнорирование гонок при чтении: даже если запись атомарна, чтение может быть небезопасным
  • выбор NSLock там, где достаточно os_unfair_lock - избыточная блокировка
  • забывают про defer для разблокировки - это приводит к deadlock при исключении

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

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