Что такое Dispatch Barrier в Grand Central Dispatch (GCD) и как вы его применяли?

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

Ответ

Dispatch Barrier — это механизм в GCD для синхронизации доступа к общему ресурсу в concurrent (параллельной) очереди. Он гарантирует, что задача, отправленная с флагом .barrier, выполнится эксклюзивно — все ранее отправленные задачи завершатся, а новые задачи будут ждать завершения барьерной.

Зачем это нужно? Для реализации шаблона "множество читателей, один писатель" (Multiple Readers, Single Writer). Операции чтения могут выполняться параллельно, а операции записи требуют эксклюзивного доступа для предотвращения состояния гонки (race condition).

Пример реализации потокобезопасного массива:

class ThreadSafeArray<T> {
    private let concurrentQueue = DispatchQueue(label: "com.example.threadSafeArray", attributes: .concurrent)
    private var array = [T]()

    // Запись (писатель) использует барьер для эксклюзивного доступа
    func append(_ element: T) {
        concurrentQueue.async(flags: .barrier) {
            self.array.append(element)
        }
    }

    // Чтение (читатели) выполняются параллельно, если нет активного барьера
    var values: [T] {
        var resultCopy = [T]()
        concurrentQueue.sync { // Используем sync для немедленного возврата результата
            resultCopy = self.array
        }
        return resultCopy
    }
}

// Использование
let safeArray = ThreadSafeArray<Int>()
DispatchQueue.concurrentPerform(iterations: 100) { i in
    safeArray.append(i) // Барьер гарантирует корректность записи
}
print(safeArray.values.count) // Чтение выполняется параллельно и безопасно

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