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
.
Method | 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
.
Method | 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_lock
y 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.
event
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
.
Method | 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]
Secciones relacionadas
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.