Namespaces
Variants

std:: shared_mutex

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
(C++11)
shared_mutex
(C++17)
Generic lock management
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
Definido en el encabezado <shared_mutex>
class shared_mutex ;
(desde C++17)

La clase shared_mutex es un primitivo de sincronización que puede utilizarse para proteger datos compartidos de ser accedidos simultáneamente por múltiples hilos. A diferencia de otros tipos de mutex que facilitan acceso exclusivo, un shared_mutex tiene dos niveles de acceso:

  • shared - varios hilos pueden compartir la propiedad del mismo mutex.
  • exclusive - solo un hilo puede poseer el mutex.

Si un hilo ha adquirido el bloqueo exclusivo (a través de lock , try_lock ), ningún otro hilo puede adquirir el bloqueo (incluyendo el compartido ).

Si un hilo ha adquirido el bloqueo compartido (a través de lock_shared , try_lock_shared ), ningún otro hilo puede adquirir el bloqueo exclusivo , pero sí puede adquirir el bloqueo compartido .

Solo cuando el exclusive lock no ha sido adquirido por ningún thread, el shared lock puede ser adquirido por múltiples threads.

Dentro de un hilo, solo se puede adquirir un bloqueo ( shared o exclusive ) al mismo tiempo.

Los mutex compartidos son especialmente útiles cuando los datos compartidos pueden ser leídos 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 requisitos de SharedMutex y StandardLayoutType .

Contenidos

Tipos de miembros

Tipo de miembro Definición
native_handle_type ( opcional* ) definido por la implementación

Funciones miembro

construye el mutex
(función miembro pública)
destruye el mutex
(función miembro pública)
operator=
[deleted]
no asignable por 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, retorna 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, retorna si el mutex no está disponible
(función miembro pública)
desbloquea el mutex (propiedad compartida)
(función miembro pública)
Manejador nativo
retorna el objeto de manejador nativo definido por la implementación subyacente
(función miembro pública)

Ejemplo

La salida a continuación fue generada en una máquina de un solo núcleo. Cuando thread1 comienza, entra al bucle por primera vez y llama a increment() seguido de get() . Sin embargo, antes de que pueda imprimir el valor devuelto en std:: cout , el planificador pone a thread1 en suspensión y despierta a thread2 , que obviamente tiene tiempo suficiente para ejecutar las tres iteraciones del bucle de una vez. De vuelta en thread1 , todavía en la primera iteración del bucle, finalmente imprime su copia local del valor del contador, que es 1 , en std::cout y luego ejecuta las dos iteraciones restantes del bucle. En una máquina multi-núcleo, ninguno de los hilos se pone en suspensión y es más probable que la salida esté en orden ascendente.

#include <iostream>
#include <mutex>
#include <shared_mutex>
#include <syncstream>
#include <thread>
class ThreadSafeCounter
{
public:
    ThreadSafeCounter() = default;
    // Multiple threads/readers can read the counter's value at the same time.
    unsigned int get() const
    {
        std::shared_lock lock(mutex_);
        return value_;
    }
    // Only one thread/writer can increment/write the counter's value.
    void increment()
    {
        std::unique_lock lock(mutex_);
        ++value_;
    }
    // Only one thread/writer can reset/write the counter's value.
    void reset()
    {
        std::unique_lock lock(mutex_);
        value_ = 0;
    }
private:
    mutable std::shared_mutex mutex_;
    unsigned int value_{};
};
int main()
{
    ThreadSafeCounter counter;
    auto increment_and_print = [&counter]()
    {
        for (int i{}; i != 3; ++i)
        {
            counter.increment();
            std::osyncstream(std::cout)
                << std::this_thread::get_id() << ' ' << counter.get() << '\n';
        }
    };
    std::thread thread1(increment_and_print);
    std::thread thread2(increment_and_print);
    thread1.join();
    thread2.join();
}

Salida posible:

123084176803584 2
123084176803584 3
123084176803584 4
123084185655040 1
123084185655040 5
123084185655040 6

Véase también

proporciona funcionalidad de exclusión mutua compartida e implementa bloqueo con tiempo de espera
(clase)
implementa un envoltorio de propiedad de mutex compartido movible
(plantilla de clase)
implementa un envoltorio de propiedad de mutex movible
(plantilla de clase)