std::shared_mutex
Definido en el archivo de encabezado <shared_mutex>
|
||
class shared_mutex; |
(desde C++17) | |
La clase shared_mutex
es una primitiva de sincronización que se puede utilizar para proteger datos compartidos de un acceso simultáneo por varios hilos/subprocesos. A diferencia de otros tipos mutex que facilitan el acceso exclusivo, un shared_mutex
tiene dos niveles o modalidades de acceso:
- compartido - varios hilos pueden tomar posesión del mismo mutex.
- exclusivo - solo un hilo puede poseer el mutex.
Si un hilo ha adquirido el bloqueo exclusivo (a través de lock o try_lock), ningún otro hilo puede adquirir el bloqueo (incluido el compartido).
Si un hilo ha adquirido el bloqueo compartido a través de lock_shared o try_lock_shared), ningún otro hilo puede adquirir el bloqueo (incluido el bloqueo exclusivo, pero puede adquirir el bloqueo compartido.
Solo cuando el bloqueo exclusivo no ha sido adquirido por ningún hilo, el bloqueo compartido puede adquirirse por múltiples hilos.
Dentro de un hilo, solo se puede adquirir un bloqueo (compartido o exclusivo) a la vez.
Los mutexes compartidos son especialmente útiles cuando los datos compartidos pueden leerse de forma segura por cualquier número de hilos simultáneamente, pero un hilo solo puede escribir los mismos datos cuando ningún otro hilo esté leyendo o escribiendo al mismo tiempo.
La clase shared_mutex
satisface todos los requerimientos de SharedMutex y StandardLayoutType.
Contenido |
[editar] Tipos miembro
Tipo miembro | Definición |
native_handle_type (no siempre está presente)
|
definido por la implementación |
[editar] Funciones miembro
Construye el mutex (función miembro pública) | |
Destruye el mutex (función miembro pública) | |
operator= [eliminada] |
No es asignable mediante copia (función miembro pública) |
Bloqueo exclusivo | |
Bloquea el mutex; se bloquea si el mutex no está disponible (función miembro pública) | |
Intenta bloquear el mutex; regresa si el mutex no está disponible (función miembro pública) | |
Desbloquea el mutex (función miembro pública) | |
Bloqueo compartido | |
Bloquea el mutex para propiedad compartida; se bloquea si el mutex no está disponible (función miembro pública) | |
Intenta bloquear el mutex para propiedad compartida; regresa si el mutex no está disponible (función miembro pública) | |
Desbloquea el mutex (propiedad compartida) (función miembro pública) | |
Identificador nativo | |
Devuelve el identificador nativo subyacente definido por la implementación (función miembro pública) |
[editar] Ejemplo
#include <iostream> #include <mutex> #include <shared_mutex> #include <thread> class ThreadSafeCounter { public: ThreadSafeCounter() = default; // Múltiples hilos/lectores pueden leer el valor del contador al mismo tiempo. unsigned int get() const { std::shared_lock lock(mutex_); return value_; } // Solo un hilo/escritor puede incrementar/escribir el valor del contador. unsigned int increment() { std::unique_lock lock(mutex_); return ++value_; } // Solo un hilo/escritor puede restablecer/escribir el valor del contador. void reset() { std::unique_lock lock(mutex_); value_ = 0; } private: mutable std::shared_mutex mutex_; unsigned int value_ = 0; }; int main() { ThreadSafeCounter counter; auto increment_and_print = [&counter]() { for (int i = 0; i < 3; i++) { std::cout << std::this_thread::get_id() << ' ' << counter.increment() << '\n'; // Nota: Escribir a std::cout de hecho también necesita sincronizarse // por otro std::mutex. Se ha omitido para hacer corto el ejemplo. } }; std::thread thread1(increment_and_print); std::thread thread2(increment_and_print); thread1.join(); thread2.join(); } // Explicación: El resultado a continuación se generó en una máquina de un solo // núcleo. Cuando thread1 comienza, ingresa al bucle por primera vez y llama a // increment() seguido de get(). Sin embargo, antes de que pueda imprimir el // valor devuelto a std::cout, el programador pone a thread1 en suspensión y // despierta a thread2, que obviamente, tiene tiempo suficiente para ejecutar // las tres iteraciones del bucle a la vez. De regreso a thread1, aún en la // primera iteración del ciclo, finalmente imprime su copia local del valor del // contador, que es 1, a std::cout y luego ejecuta las dos iteraciones restantes // del bucle. En una máquina de varios núcleos, ninguno de los hilos se coloca en // modo de suspensión y es más probable que la salida esté en orden ascendente.
Posible salida:
123084176803584 2 123084176803584 3 123084176803584 4 123084185655040 1 123084185655040 5 123084185655040 6
[editar] Véase también
(C++14) |
Proporciona un servicio de exclusión mutua compartida e implementa bloqueo con un tiempo de espera. (clase) |
(C++14) |
Implementa un envoltorio de propiedad de un mutex movible. (plantilla de clase) |
(C++11) |
Implementa un envoltorio de propiedad de mutex movible. (plantilla de clase) |