Можно ли безопасно использовать общие ресурсы между разными RunLoop в iOS?

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

Ответ

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

Способы синхронизации:

  1. Serial DispatchQueue: Гарантирует последовательный доступ.
  2. Concurrent DispatchQueue с барьером: Для эффективного чтения/записи.
  3. Мьютексы (NSLock, os_unfair_lock): Для низкоуровневой синхронизации.

Пример с использованием DispatchQueue:

// Потокобезопасный контейнер
class SharedResource<T> {
    private var value: T
    private let queue = DispatchQueue(label: "com.example.shared", attributes: .concurrent)

    init(_ value: T) { self.value = value }

    func read() -> T {
        return queue.sync { value }
    }

    func write(_ newValue: T) {
        queue.async(flags: .barrier) { self.value = newValue }
    }
}

Вывод: Сам RunLoop не обеспечивает синхронизацию. Используйте стандартные механизмы многопоточности для защиты общих данных.