Namensräume
Varianten
Aktionen

std::shared_mutex

Von cppreference.com
< cpp‎ | thread
 
 
Bibliothek für nebenläufige Programmierung
Threads
(C++11)
(C++20)
this_thread Namespace
(C++11)
(C++11)
(C++11)
Kooperatives Beenden
Gegenseitiger Ausschluss
(C++11)
shared_mutex
(C++17)
Allgemeines Sperrungsmanagement
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Bedingungsvariablen
(C++11)
Semaphoren
Latches und Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
(C++11)
Sichere Wiederherstellung
(C++26)
Hazard Pointer
Atomare Typen
(C++11)
(C++20)
Initialisierung von atomaren Typen
(C++11)(veraltet in C++20)
(C++11)(veraltet in C++20)
Speicherordnung
(C++11)(deprecated in C++26)
Freie Funktionen für atomare Operationen
Freie Funktionen für atomare Flags
 
 
Definiert in Header <shared_mutex>
class shared_mutex;
(seit C++17)

Die Klasse shared_mutex ist ein Synchronisationsprimitiv, das verwendet werden kann, um den Zugriff auf geteilte Daten zu schützen, damit sie nicht gleichzeitig von mehreren Threads zugegriffen werden können. Im Gegensatz zu anderen Mutex-Typen, die exklusiven Zugriff ermöglichen, hat ein shared_mutex zwei Zugriffsebenen:

  • shared (geteilt) - mehrere Threads können den Besitz desselben Mutex teilen.
  • exclusive (exklusiv) - nur ein Thread kann den Mutex besitzen.

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

Wenn ein Thread den shared Lock erworben hat (über lock_shared, try_lock_shared), kann kein anderer Thread den exklusiven Lock erwerben, aber er kann den shared Lock erwerben.

Nur wenn der exklusive Lock von keinem Thread erworben wurde, kann der shared Lock von mehreren Threads erworben werden.

Innerhalb eines Threads kann zu jeder Zeit nur ein Lock (shared oder exclusive) erworben werden.

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

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

Inhalt

[bearbeiten] Member types

Mitgliedertyp Definition
native_handle_type (optional*) implementierungsabhängig[bearbeiten]

[bearbeiten] Member functions

konstruiert den Mutex
(public member function) [edit]
zerstört den Mutex
(public member function) [edit]
operator=
[gelöscht]
nicht kopierbar
(public member function) [edit]
Exklusives Sperren
sperrt den Mutex, blockiert, wenn der Mutex nicht verfügbar ist
(public member function) [edit]
versucht, den Mutex zu sperren, kehrt zurück, wenn der Mutex nicht verfügbar ist
(public member function) [edit]
entsperrt den Mutex
(public member function) [edit]
Gemeinsames Sperren
sperrt den Mutex für gemeinsamen Besitz, blockiert, wenn der Mutex nicht verfügbar ist
(public member function) [edit]
versucht, den Mutex für gemeinsamen Besitz zu sperren, kehrt zurück, wenn der Mutex nicht verfügbar ist
(public member function) [edit]
entsperrt den Mutex (gemeinsamer Besitz)
(public member function) [edit]
Native handle
gibt das implementierungsabhängige native Handle-Objekt zurück
(public member function) [bearbeiten]

[bearbeiten] Beispiel

Die untenstehende Ausgabe wurde auf einem Single-Core-Rechner 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 nach std::cout ausgeben kann, versetzt der Scheduler thread1 in den Schlaf und weckt thread2 auf, das offensichtlich genügend Zeit hat, 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, nämlich 1, nach std::cout aus und führt dann die verbleibenden zwei Schleifendurchläufe aus. Auf einem Multi-Core-Rechner wird keiner der Threads in den Schlaf versetzt, und die Ausgabe ist eher aufsteigend.

#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

[bearbeiten] Siehe auch

bietet gemeinsame Gegenseitiger-Ausschluss-Funktionen und implementiert ein Sperren mit Timeout
(Klasse) [bearbeiten]
implementiert verschiebbaren Shared-Mutex-Besitz-Wrapper
(Klassenvorlage) [bearbeiten]
implementiert verschiebbaren Mutex-Besitz-Wrapper
(Klassenvorlage) [bearbeiten]