Ответ
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 (последовательной) очереди они не имеют смысла, так как все задачи и так выполняются последовательно.