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
Défini dans l'en-tête <shared_mutex>
class shared_mutex ;
(depuis C++17)

La classe shared_mutex est un primitif de synchronisation qui peut être utilisé pour protéger des données partagées contre un accès simultané par plusieurs threads. Contrairement aux autres types de mutex qui facilitent l'accès exclusif, un shared_mutex possède deux niveaux d'accès :

  • shared - plusieurs threads peuvent partager la propriété du même mutex.
  • exclusive - un seul thread peut posséder le mutex.

Si un thread a acquis le verrou exclusif (via lock , try_lock ), aucun autre thread ne peut acquérir le verrou (y compris le partagé ).

Si un thread a acquis le verrou partagé (via lock_shared , try_lock_shared ), aucun autre thread ne peut acquérir le verrou exclusif , mais peut acquérir le verrou partagé .

Seulement lorsque le verrou exclusif n'a été acquis par aucun thread, le verrou partagé peut être acquis par plusieurs threads.

Au sein d'un même thread, un seul verrou ( shared ou exclusive ) peut être acquis simultanément.

Les mutex partagés sont particulièrement utiles lorsque les données partagées peuvent être lues en toute sécurité par n'importe quel nombre de threads simultanément, mais un thread ne peut écrire les mêmes données qu'aucun autre thread ne lit ou n'écrit en même temps.

La classe shared_mutex satisfait toutes les exigences de SharedMutex et de StandardLayoutType .

Table des matières

Types membres

Type de membre Définition
native_handle_type ( optionnel* ) défini par l'implémentation

Fonctions membres

construit le mutex
(fonction membre publique)
détruit le mutex
(fonction membre publique)
operator=
[deleted]
non assignable par copie
(fonction membre publique)
Verrouillage exclusif
verrouille le mutex, bloque si le mutex n'est pas disponible
(fonction membre publique)
tente de verrouiller le mutex, retourne si le mutex n'est pas disponible
(fonction membre publique)
déverrouille le mutex
(fonction membre publique)
Verrouillage partagé
verrouille le mutex en propriété partagée, bloque si le mutex n'est pas disponible
(fonction membre publique)
tente de verrouiller le mutex en propriété partagée, retourne si le mutex n'est pas disponible
(fonction membre publique)
déverrouille le mutex (propriété partagée)
(fonction membre publique)
Handle natif
retourne l'objet handle natif défini par l'implémentation sous-jacente
(fonction membre publique)

Exemple

La sortie ci-dessous a été générée sur une machine monocœur. Lorsque thread1 démarre, il entre dans la boucle pour la première fois et appelle increment() suivi de get() . Cependant, avant qu'il ne puisse imprimer la valeur retournée vers std:: cout , l'ordonnanceur met thread1 en veille et réveille thread2 , qui a évidemment assez de temps pour exécuter les trois itérations de boucle d'un coup. De retour à thread1 , toujours dans la première itération de boucle, il imprime finalement sa copie locale de la valeur du compteur, qui est 1 , vers std::cout puis exécute les deux itérations de boucle restantes. Sur une machine multicœur, aucun thread n'est mis en veille et la sortie a plus de chances d'être dans l'ordre croissant.

#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();
}

Sortie possible :

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

Voir aussi

fournit un mécanisme d'exclusion mutuelle partagé et implémente le verrouillage avec un délai d'expiration
(classe)
implémente un wrapper de propriété de mutex partagé déplaçable
(modèle de classe)
implémente un wrapper de propriété de mutex déplaçable
(modèle de classe)