std:: lock_guard
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
|
Definiert im Header
<mutex>
|
||
|
template
<
class
Mutex
>
class lock_guard ; |
(seit C++11) | |
Die Klasse
lock_guard
ist ein Mutex-Wrapper, der einen praktischen
RAII-Stil
Mechanismus bereitstellt, um einen Mutex für die Dauer eines gültigen Blocks zu besitzen.
Wenn ein
lock_guard
-Objekt erstellt wird, versucht es, den Besitz des übergebenen Mutex zu übernehmen. Wenn der Kontrollfluss den Gültigkeitsbereich verlässt, in dem das
lock_guard
-Objekt erstellt wurde, wird der
lock_guard
zerstört und der Mutex freigegeben.
Die
lock_guard
-Klasse ist nicht kopierbar.
Inhaltsverzeichnis |
Template-Parameter
| Mutex | - | der Typ des zu sperrenden Mutex. Der Typ muss die BasicLockable Anforderungen erfüllen |
Mitgliedertypen
| Mitgliedstyp | Definition |
mutex_type
|
Mutex |
Memberfunktionen
Konstruiert einen
lock_guard
, optional sperrend das gegebene Mutex
(öffentliche Elementfunktion) |
|
zerstört das
lock_guard
-Objekt, entsperrt das zugrundeliegende Mutex
(öffentliche Elementfunktion) |
|
|
operator=
[deleted]
|
nicht kopierzuweisbar
(öffentliche Elementfunktion) |
Hinweise
Ein häufiger Anfängerfehler ist es, zu vergessen, einer
lock_guard
-Variable einen Namen zu geben, wie beispielsweise durch
std
::
lock_guard
{
mtx
}
. Dies konstruiert ein PRvalue-Objekt, das sofort zerstört wird, wodurch tatsächlich keine Sperre erstellt wird, die einen Mutex für den Rest des Gültigkeitsbereichs hält.
|
std::scoped_lock
bietet eine Alternative zu
|
(seit C++17) |
Beispiel
Demonstriert sichere und unsichere Inkrementierungen einer volatile-Variable durch zwei Threads.
#include <iostream> #include <mutex> #include <string_view> #include <syncstream> #include <thread> volatile int g_i = 0; std::mutex g_i_mutex; // schützt g_i void safe_increment(int iterations) { const std::lock_guard<std::mutex> lock(g_i_mutex); while (iterations-- > 0) g_i = g_i + 1; std::cout << "thread #" << std::this_thread::get_id() << ", g_i: " << g_i << '\n'; // g_i_mutex wird automatisch freigegeben, wenn lock den Gültigkeitsbereich verlässt } void unsafe_increment(int iterations) { while (iterations-- > 0) g_i = g_i + 1; std::osyncstream(std::cout) << "thread #" << std::this_thread::get_id() << ", g_i: " << g_i << '\n'; } int main() { auto test = [](std::string_view fun_name, auto fun) { g_i = 0; std::cout << fun_name << ":\nbefore, g_i: " << g_i << '\n'; { std::jthread t1(fun, 1'000'000); std::jthread t2(fun, 1'000'000); } std::cout << "after, g_i: " << g_i << "\n\n"; }; test("safe_increment", safe_increment); test("unsafe_increment", unsafe_increment); }
Mögliche Ausgabe:
safe_increment: before, g_i: 0 thread #140121493231360, g_i: 1000000 thread #140121484838656, g_i: 2000000 after, g_i: 2000000 unsafe_increment: before, g_i: 0 thread #140121484838656, g_i: 1028945 thread #140121493231360, g_i: 1034337 after, g_i: 1034337
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| LWG 2981 | C++17 |
redundanter Deduction Guide von
lock_guard<Mutex>
wurde bereitgestellt
|
entfernt |
Siehe auch
|
(C++11)
|
implementiert beweglichen Mutex-Eigentums-Wrapper
(Klassen-Template) |
|
(C++17)
|
Deadlock-vermeidender RAII-Wrapper für mehrere Mutexe
(Klassen-Template) |