Estructuras de datos de sincronización

El Runtime de simultaneidad proporciona varias estructuras de datos que permiten sincronizar el acceso a datos compartidos desde varios subprocesos. Estas estructuras de datos son útiles cuando ha compartido datos que modifica con poca frecuencia. Un objeto de sincronización, por ejemplo, una sección crítica, ocasiona que otros subprocesos esperen hasta que el recurso compartido esté disponible. Por lo tanto, si usa un objeto para sincronizar el acceso a los datos que se usan con frecuencia, puede perder escalabilidad en su aplicación. La Biblioteca de patrones paralelos (PPL) proporciona la clase concurrency::combinable, que permite compartir un recurso entre varios subprocesos o tareas sin necesidad de sincronización. Para más información sobre la clase combinable, consulte Contenedores y objetos paralelos.

Secciones

En este tema se describen los siguientes tipos de bloques de mensajes asincrónicos con detalle:

critical_section

La clase concurrency::critical_section representa un objeto de exclusión mutua cooperativa que se suspende en favor de otras tareas en lugar de suspenderlas. Las secciones críticas son útiles cuando varios subprocesos requieren acceso exclusivo de lectura y escritura a los datos compartidos.

La clase critical_section es no reentrante. El método concurrency::critical_section::lock produce una excepción de tipo concurrency::improper_lock si es llamado por el subproceso que ya posee el bloqueo.

Métodos y características

En la tabla siguiente se muestran los métodos importantes definidos por la clase critical_section.

Método Descripción
lock Adquiere la sección crítica. El contexto de llamada se bloquea hasta que adquiere el bloqueo.
try_lock Intenta adquirir la sección crítica, pero no bloquea.
unlock Libera la sección crítica.

[Arriba]

reader_writer_lock

La clase concurrency::reader_writer_lock proporciona operaciones de lectura y escritura seguras para subprocesos de datos compartidos. Use bloqueos de lector y escritor cuando varios subprocesos requieran acceso de lectura simultáneo a un recurso compartido, pero rara vez escriban en ese recurso compartido. Esta clase solo proporciona acceso de escritura de subproceso a un objeto en cualquier momento.

La clase reader_writer_lock puede funcionar mejor que la clase critical_section porque un objeto critical_section adquiere acceso exclusivo a un recurso compartido, lo que impide el acceso de lectura simultáneo.

Como la clase critical_section, la clase reader_writer_lock representa un objeto de exclusión mutua cooperativa que se suspende en favor de otras tareas en lugar de suspenderlas.

Cuando un subproceso que debe escribir en un recurso compartido adquiere un bloqueo de lector y escritor, otros subprocesos que también deben tener acceso al recurso se bloquean hasta que el escritor libere el bloqueo. La clase reader_writer_lock es un ejemplo de un bloqueo de preferencia de escritura, que es un bloqueo que desbloquea los escritores en espera antes de desbloquear los lectores en espera.

Al igual que la clase critical_section, la clase reader_writer_lock no es reentrante. Los métodos concurrency::reader_writer_lock::lock y concurrency::reader_writer_lock::lock_read inician una excepción de tipo improper_lock si un subproceso que ya posee el bloqueo los llama.

Nota:

Dado que la reader_writer_lock clase no es reentrante, no se puede actualizar un bloqueo de solo lectura a un bloqueo de lector/escritor o cambiar a una versión anterior un bloqueo de lector/escritor de modo que sea un bloqueo de solo lectura. La realización de cualquiera de estas operaciones genera un comportamiento no especificado.

Métodos y características

En la tabla siguiente se muestran los métodos importantes definidos por la clase reader_writer_lock.

Método Descripción
lock Adquiere acceso de lectura y escritura al bloqueo.
try_lock Intenta adquirir acceso de lectura y escritura al bloqueo, pero no bloquea.
lock_read Adquiere acceso de lectura y escritura al bloqueo.
try_lock_read Intenta adquirir acceso de lectura y escritura al bloqueo, pero no se bloquea.
unlock Libera el bloqueo.

[Arriba]

scoped_lock and scoped_lock_read

Las clases critical_section y reader_writer_lock proporcionan clases auxiliares anidadas que simplifican la forma en que se trabaja con objetos de exclusión mutua. Estas clases auxiliares se conocen como bloqueos con ámbito.

La clase critical_section contiene la clase concurrency::critical_section::scoped_lock. El constructor adquiere el acceso al objeto critical_section proporcionado; el destructor libera el acceso a ese objeto. La clase reader_writer_lock contiene la clase concurrency::reader_writer_lock::scoped_lock, que se parece critical_section::scoped_lock, excepto que administra el acceso de escritura al objeto proporcionado reader_writer_lock. La clase reader_writer_lock también contiene la clase concurrency::reader_writer_lock::scoped_lock_read. Esta clase administra el acceso de lectura al objeto proporcionado reader_writer_lock.

Los bloqueos con ámbito proporcionan varias ventajas cuando se trabaja con objetos critical_section y reader_writer_lock manualmente. Normalmente, asigna un bloqueo con ámbito en la pila. Un bloqueo con ámbito libera automáticamente el acceso a su objeto de exclusión mutua cuando se destruye; por consiguiente, no se desbloquea manualmente el objeto subyacente. Este modelo resulta útil cuando una función contiene varias instrucciones return. Los bloqueos con ámbito también pueden ayudarle a escribir código seguro para excepciones. Cuando una instrucción throw ocasiona que la pila se desenrede, se llama al destructor para cualquier bloqueo con ámbito activo y, por lo tanto, el objeto de exclusión mutua siempre se libera correctamente.

Nota:

Cuando use las clases critical_section::scoped_lock, reader_writer_lock::scoped_locky reader_writer_lock::scoped_lock_read, no libere manualmente el acceso al objeto de exclusión mutua subyacente. Esto puede poner el runtime en un estado no válido.

evento

La clase concurrency::event representa un objeto de sincronización cuyo estado se puede señalizar o no señalizar. A diferencia de los objetos de sincronización, como secciones críticas, cuyo propósito es proteger el acceso a datos compartidos, los eventos sincronizan el flujo de sincronización de ejecución.

La clase event es útil cuando una tarea ha completado el trabajo para otra tarea. Por ejemplo, una tarea podría indicar otra tarea que tiene datos de lectura de una conexión de red o de un archivo.

Métodos y características

En la tabla siguiente se muestran los métodos importantes definidos por la clase event.

Método Descripción
wait Espera a que se señale el evento.
set Establece el evento en el estado señalado.
reset Establece el evento en un estado no señalado.
wait_for_multiple Espera a que se señalen varios eventos.

Ejemplo

Para ver un ejemplo que muestra cómo usar la clase event, consulte Comparar estructuras de datos de sincronización con la API de Windows.

[Arriba]

Comparación de estructuras de datos de sincronización con la API de Windows
Compara el comportamiento de las estructuras de datos de sincronización con las que proporciona la API de Windows.

Runtime de simultaneidad
Se describe el Runtime de simultaneidad, que simplifica la programación en paralelo, y contiene vínculos a los temas relacionados.