Что такое барьерная операция (barrier) в GCD и чем она отличается от обычной?

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

Ответ

Барьерная операция в GCD — это задача в concurrent (параллельной) очереди, которая выполняется эксклюзивно. Все задачи, добавленные в очередь до барьера, выполняются параллельно. Барьерная задача запускается только после их завершения, и пока она выполняется, новые задачи не начинаются. После завершения барьера очередь возобновляет параллельное выполнение.

Обычная операция в concurrent очереди выполняется параллельно с другими задачами без каких-либо ограничений.

Ключевое отличие: Барьер обеспечивает эксклюзивный доступ для синхронизации записи в общий ресурс, обычная операция — нет.

Типичное применение: Thread-safe операции записи или модификации общего ресурса (например, словаря или массива) в concurrent очереди.

Пример:

let concurrentQueue = DispatchQueue(label: "com.example.cache", attributes: .concurrent)
var cache: [String: Data] = [:]

// Множественные параллельные чтения (обычные операции)
func read(from key: String) -> Data? {
    concurrentQueue.sync { // .sync для немедленного возврата значения
        return cache[key]
    }
}

// Запись требует эксклюзивного доступа (барьерная операция)
func write(_ data: Data, for key: String) {
    concurrentQueue.async(flags: .barrier) {
        cache[key] = data
    }
}

Важно: Барьеры имеют смысл только в concurrent очередях, созданных с атрибутом .concurrent. В serial (последовательных) очередях все задачи и так выполняются по одной, поэтому барьер не нужен.