Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про Swift : Swift, lazy var, thread safety, concurrency, initialization

Является ли lazy var потокобезопасным?

Вопрос проверяет понимание потокобезопасности lazy-свойств в Swift и их поведения в многопоточной среде.

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

Нет, lazy var по умолчанию не является потокобезопасным в Swift. Если несколько потоков одновременно обратятся к ещё неинициализированному lazy-свойству, оно может быть инициализировано несколько раз, что приведёт к гонкам данных и непредсказуемому поведению. Для обеспечения потокобезопасности необходимо использовать синхронизацию, например, через dispatch queues, мьютексы или обёртки вроде @Atomic. Начиная с Swift 5.5, можно использовать акторы (actors) для изоляции состояния.

Длинный ответ

Ключевое слово lazy в Swift позволяет отложить инициализацию свойства до момента его первого использования. Это полезно для оптимизации, когда создание ресурса дорого или зависит от других, ещё не готовых данных. Однако, стандартная реализация lazy var не гарантирует атомарность при одновременном доступе из нескольких потоков.

Проблема потокобезопасности

Механизм отложенной инициализации внутри себя использует флаг для отслеживания состояния. Если два потока одновременно проверят, что свойство ещё не инициализировано, оба могут запустить код инициализации, что может привести к:

  • Двойному выполнению дорогой операции (например, загрузки данных).
  • Присвоению разных экземпляров (если инициализация создаёт новый объект).
  • Случайным сбоям или неконсистентному состоянию.

Пример небезопасного lazy var

class DataManager {
    lazy var expensiveResource: String = {
        // Дорогая операция, например, чтение файла
        print("Инициализация ресурса")
        return "Данные"
    }()
}

let manager = DataManager()
DispatchQueue.concurrentPerform(iterations: 5) { _ in
    _ = manager.expensiveResource // Может напечатать "Инициализация ресурса" несколько раз
}

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

1. Использование dispatch_once (устарел в Swift, но возможен через Objective-C runtime).
2. Синхронизация с помощью DispatchQueue или NSLock.
3. Обёртка с атомарным доступом (например, кастомное свойство @Atomic).
4. Использование акторов (actors) в Swift Concurrency для изоляции состояния.

Пример с потокобезопасной обёрткой

import Foundation

@propertyWrapper
struct AtomicLazy {
    private var storage: T?
    private let lock = NSLock()
    private let initializer: () -> T
    
    init(wrappedValue initializer: @escaping @autoclosure () -> T) {
        self.initializer = initializer
    }
    
    var wrappedValue: T {
        get {
            lock.lock()
            defer { lock.unlock() }
            if storage == nil {
                storage = initializer()
            }
            return storage!
        }
    }
}

class SafeDataManager {
    @AtomicLazy var expensiveResource: String = {
        print("Потокобезопасная инициализация")
        return "Данные"
    }()
}

Вывод: Используйте стандартный lazy var только в однопоточном контексте или когда вы уверены, что первое обращение произойдёт до создания других потоков. В многопоточных приложениях, таких как iOS/macOS приложения с UI и фоновыми задачами, обязательно добавляйте синхронизацию для lazy-свойств, к которым возможен конкурентный доступ.

  • Аватар

    iOS Guru

    Roman Isakov

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.

Уровень

  • Рейтинг:

    3

  • Сложность:

    6

Навыки

  • Swift

    Swift

Ключевые слова

#Swift

#lazy var

#thread safety

#concurrency

#initialization

Подпишись на iOS Developer в телеграм

  • Аватар

    iOS Guru

    Roman Isakov

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.