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
Definiert im Header <shared_mutex>
class shared_mutex ;
(seit C++17)

Die shared_mutex -Klasse ist ein Synchronisationsprimitiv, das verwendet werden kann, um gemeinsame Daten vor gleichzeitigem Zugriff durch mehrere Threads zu schützen. Im Gegensatz zu anderen Mutex-Typen, die exklusiven Zugriff ermöglichen, bietet ein shared_mutex zwei Zugriffsebenen:

  • shared - mehrere Threads können gemeinsamen Besitz desselben Mutex haben.
  • exclusive - nur ein Thread kann den Mutex besitzen.

Wenn ein Thread den exklusiven Lock erworben hat (durch lock , try_lock ), können keine anderen Threads den Lock erwerben (einschließlich des shared ).

Wenn ein Thread den shared Lock erworben hat (durch lock_shared , try_lock_shared ), kann kein anderer Thread den exclusive Lock erwerben, aber kann den shared Lock erwerben.

Nur wenn die exklusive Sperre von keinem Thread erworben wurde, kann die gemeinsame Sperre von mehreren Threads erworben werden.

Innerhalb eines Threads kann nur eine Sperre ( shared oder exclusive ) gleichzeitig erworben werden.

Shared Mutexe sind besonders nützlich, wenn gemeinsame Daten von beliebig vielen Threads gleichzeitig sicher gelesen werden können, aber ein Thread dieselben Daten nur dann schreiben darf, wenn kein anderer Thread gleichzeitig liest oder schreibt.

Die shared_mutex -Klasse erfüllt alle Anforderungen von SharedMutex und StandardLayoutType .

Inhaltsverzeichnis

Mitgliedertypen

Mitgliedertyp Definition
native_handle_type ( optional* ) implementierungsdefiniert

Memberfunktionen

Konstruiert den Mutex
(öffentliche Elementfunktion)
Zerstört den Mutex
(öffentliche Elementfunktion)
operator=
[deleted]
Nicht kopierzuweisbar
(öffentliche Elementfunktion)
Exklusives Sperren
Sperrt den Mutex, blockiert falls der Mutex nicht verfügbar ist
(öffentliche Elementfunktion)
Versucht den Mutex zu sperren, kehrt zurück falls der Mutex nicht verfügbar ist
(öffentliche Elementfunktion)
Entsperrt den Mutex
(öffentliche Elementfunktion)
Gemeinsames Sperren
Sperrt den Mutex für gemeinsamen Besitz, blockiert falls der Mutex nicht verfügbar ist
(öffentliche Elementfunktion)
Versucht den Mutex für gemeinsamen Besitz zu sperren, kehrt zurück falls der Mutex nicht verfügbar ist
(öffentliche Elementfunktion)
Entsperrt den Mutex (gemeinsamer Besitz)
(öffentliche Elementfunktion)
Systemeigenes Handle
Gibt das zugrundeliegende implementierungsdefinierte systemeigene Handle-Objekt zurück
(öffentliche Elementfunktion)

Beispiel

Die folgende Ausgabe wurde auf einem Single-Core-System erzeugt. Wenn thread1 startet, tritt es zum ersten Mal in die Schleife ein und ruft increment() gefolgt von get() auf. Bevor es jedoch den zurückgegebenen Wert an std:: cout ausgeben kann, setzt der Scheduler thread1 schlafen und weckt thread2 , welches offensichtlich genug Zeit hat, um alle drei Schleifendurchläufe auf einmal auszuführen. Zurück zu thread1 , immer noch im ersten Schleifendurchlauf, gibt es schließlich seine lokale Kopie des Zählerwerts, der 1 beträgt, an std::cout aus und führt dann die verbleibenden zwei Schleifendurchläufe aus. Auf einem Multi-Core-System wird keiner der Threads schlafen gesetzt und die Ausgabe ist wahrscheinlicher in aufsteigender Reihenfolge.

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

Mögliche Ausgabe:

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

Siehe auch

bietet gemeinsame gegenseitige Ausschlusseinrichtung und implementiert Sperren mit Timeout
(Klasse)
implementiert beweglichen Shared-Mutex-Eigentums-Wrapper
(Klassentemplate)
implementiert beweglichen Mutex-Eigentums-Wrapper
(Klassentemplate)