Что такое проблема readers-writers и как её решить в Swift?

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

Ответ

Проблема readers-writers (читатели-писатели) — это классическая задача синхронизации, где множество потоков могут одновременно читать общие данные, но запись требует эксклюзивного доступа (только один писатель и никаких читателей).

Цель: максимизировать параллельное чтение, обеспечивая целостность данных при записи.

Решение в Swift с использованием GCD и барьерных задач (barrier):

class ThreadSafeDictionary<Key: Hashable, Value> {
    private var storage = [Key: Value]()
    // Используем concurrent очередь для параллельного чтения
    private let queue = DispatchQueue(label: "com.example.rwlock", attributes: .concurrent)

    // ЧТЕНИЕ: выполняется синхронно и параллельно
    func value(forKey key: Key) -> Value? {
        return queue.sync {
            storage[key]
        }
    }

    // ЗАПИСЬ: выполняется асинхронно с барьером для эксклюзивного доступа
    func setValue(_ value: Value, forKey key: Key) {
        queue.async(flags: .barrier) {
            self.storage[key] = value
        }
    }
}

Как это работает:

  • .sync на concurrent очереди позволяет множеству читателей выполнять код блока одновременно.
  • .barrier флаг для операции записи гарантирует, что в момент её выполнения очередь приостанавливается, и никакие другие задачи (ни чтение, ни запись) не выполняются параллельно.

Альтернативы: pthread_rwlock_t, NSLock или os_unfair_lock с подсчетом читателей.