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

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

Ответ

Нет. Несмотря на то, что структуры (value-типы) копируются при присваивании или передаче в функцию, они не являются автоматически потокобезопасными при работе с изменяемым (mutating) экземпляром, доступным из нескольких потоков.

Проблема возникает, когда:

  • У вас есть изменяемая (var) переменная структуры.
  • Несколько потоков одновременно вызывают её mutating методы или изменяют свойства.
  • Это приводит к гонке данных, так как операция += не атомарна.

Пример гонки:

struct Counter {
    var value = 0
    mutating func increment() { value += 1 }
}

var counter = Counter() // Изменяемый экземпляр
DispatchQueue.concurrentPerform(iterations: 1000) { _ in
    counter.increment() // ❌ Гонка данных! Каждый поток читает и пишет в одну область памяти.
}
// Итоговое значение `counter.value` будет случайным.

Как обеспечить потокобезопасность для структуры:

  1. Инкапсулировать в потокобезопасный класс (см. предыдущий ответ).
  2. Использовать мьютекс или очередь внутри структуры (редко, нарушает семантику value-типа).
  3. Использовать актор (actor) для управления изменяемым состоянием.
  4. Спроектировать систему так, чтобы каждый поток работал со своей копией структуры, а результаты объединялись через синхронизированный механизм.

Ключевая мысль: Потокобезопасность зависит не от типа (класс/структура), а от того, как организован доступ к изменяемому состоянию. Value-типы лишь упрощают создание изолированных копий.