DEV Community

GoyesDev
GoyesDev

Posted on

[GCD] Dispatch Barrier

Un "Dispatch Barrier" es un tipo de tarea que actúa como punto de sincronización en un DispatchQueue concurrente. La barrera asegura que la tarea especificada es la única en ejecutación en esa cola en cualquier momento. Esto ayuda a evitar carreras de datos ("data races")

Virtualmente se podría ver un "Dispatch Barrier" como una manera de convertir una cola concurrente en una serial, de forma temporal. Por esta razón, no tiene sentido aplicar la bandera .barrier en una cola serial.

Características

  • Ejecución exclusiva: Solo una tarea se puede ejecutar al tiempo.
  • Orden fijo: Las tareas despachadas antes de la barrera deben terminar antes de que esta empiece. Las tareas despachadas después de ella deben esperar a que ella termine.

¿Cómo usar un Dispatch Barrier?

En una cola concurrente, se despacha la tarea (de forma síncrona o asíncrona) con la bandera .barrier.

Ejemplo

En el siguiente ejemplo, se usa una cola concurrente para administrar unos datos de una caché. A la hora de escribir se pone una barrera para esperar a que todos los hilos terminen primero. Para leer se usa queue.sync para leer el contenido de forma segura.

class Cache {
  private let queue = DispatchQueue(label: "", attributes: .concurrent)
  private var dictionary: [String:Any] = [:]

  subscript(key: String) -> Any? {
    get {
      queue.sync {
        dictionary[key]
      }
    }
    set {
      queue.async(flags: .barrier) { 
        self.dictionary[key] = newValue 
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Reemplazo con Swift Concurrency

Se puede usar actores para evitar carreras de datos. Luego, el acceso a los recursos se hace por medio de await. Por ejemplo:

actor CacheActor {
  private var dictionary: [String:Any] = [:]

  subscript(key: String) -> Any? {
    get { dictionary[key] }
    set { dictionary[key] = newValue }
  }
}
let cache = CacheActor()
let value = await cache["key"]
Enter fullscreen mode Exit fullscreen mode

¿Cuándo usar un "Dispatch Barrier"?

Las barreras son útiles cuando se necesita escribir y leer algún recurso en un ambiente concurrente. Por ejemplo:

  • Acceso a arreglos, diccionarios, conjuntos, etc.
  • Acceso a bases de datos.

¿Cuándo NO usar un "Dispatch Barrier"?

No se debe usar un Dispatch Barrier en una cola global concurrente. Tener en cuenta que puede haber otro proceso usando la misma cola global, así que no se la debe monopolizar. En su lugar, mejor crear una cola concurrente propia.


Bibliografía

Top comments (0)