std:: lock_guard
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
|
Défini dans l'en-tête
<mutex>
|
||
|
template
<
class
Mutex
>
class lock_guard ; |
(depuis C++11) | |
La classe
lock_guard
est un wrapper de mutex qui fournit un mécanisme pratique de style
RAII
pour posséder un mutex pendant la durée d'un bloc de portée.
Lorsqu'un objet
lock_guard
est créé, il tente de prendre la possession du mutex qui lui est donné. Lorsque le contrôle quitte la portée dans laquelle l'objet
lock_guard
a été créé, le
lock_guard
est détruit et le mutex est libéré.
La classe
lock_guard
n'est pas copiable.
Table des matières |
Paramètres du modèle
| Mutex | - | le type du mutex à verrouiller. Le type doit satisfaire aux BasicLockable exigences |
Types membres
| Type de membre | Définition |
mutex_type
|
Mutex |
Fonctions membres
construit un
lock_guard
, verrouillant optionnellement le mutex donné
(fonction membre publique) |
|
détruit l'objet
lock_guard
, déverrouille le mutex sous-jacent
(fonction membre publique) |
|
|
operator=
[deleted]
|
non assignable par copie
(fonction membre publique) |
Notes
Une erreur courante chez les débutants est d'oublier de donner un nom à une variable
lock_guard
, par exemple en écrivant
std
::
lock_guard
{
mtx
}
. Cela construit un objet prvalue qui est immédiatement détruit, ne créant donc pas réellement un verrou qui maintient un mutex pour le reste de la portée.
|
std::scoped_lock
offre une alternative à
|
(depuis C++17) |
Exemple
Illustre les incréments sécurisés et non sécurisés d'une variable volatile par deux threads.
#include <iostream> #include <mutex> #include <string_view> #include <syncstream> #include <thread> volatile int g_i = 0; std::mutex g_i_mutex; // protects 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 is automatically released when lock goes out of scope } 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); }
Sortie possible :
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
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
| DR | S'applique à | Comportement publié | Comportement corrigé |
|---|---|---|---|
| LWG 2981 | C++17 |
un guide de déduction redondant de
lock_guard<Mutex>
était fourni
|
supprimé |
Voir aussi
|
(C++11)
|
implémente un wrapper de propriété de mutex déplaçable
(modèle de classe) |
|
(C++17)
|
wrapper RAII évitant les interblocages pour plusieurs mutex
(modèle de classe) |