std:: lock_guard
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
|
Definido en el encabezado
<mutex>
|
||
|
template
<
class
Mutex
>
class lock_guard ; |
(desde C++11) | |
La clase
lock_guard
es un envoltorio de mutex que proporciona un mecanismo conveniente
estilo RAII
para poseer un mutex durante la duración de un bloque de ámbito.
Cuando un objeto
lock_guard
es creado, intenta tomar posesión del mutex que se le proporciona. Cuando el control sale del ámbito en el que el objeto
lock_guard
fue creado, el
lock_guard
es destruido y el mutex es liberado.
La clase
lock_guard
no es copiable.
Contenidos |
Parámetros de plantilla
| Mutex | - | el tipo del mutex a bloquear. El tipo debe cumplir con los BasicLockable requisitos |
Tipos de miembros
| Tipo de miembro | Definición |
mutex_type
|
Mutex |
Funciones miembro
construye un
lock_guard
, opcionalmente bloqueando el mutex dado
(función miembro pública) |
|
destruye el objeto
lock_guard
, desbloquea el mutex subyacente
(función miembro pública) |
|
|
operator=
[deleted]
|
no asignable por copia
(función miembro pública) |
Notas
Un error común de principiantes es olvidar darle un nombre a una variable
lock_guard
, como por ejemplo
std
::
lock_guard
{
mtx
}
. Esto construye un objeto prvalue que se destruye inmediatamente, por lo tanto no se construye realmente un bloqueo que mantenga un mutex durante el resto del ámbito.
|
std::scoped_lock
ofrece una alternativa para
|
(since C++17) |
Ejemplo
Demuestra incrementos seguros e inseguros de una variable volátil por dos hilos.
#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); }
Salida posible:
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
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 2981 | C++17 |
se proporcionó una guía de deducción redundante de
lock_guard<Mutex>
|
eliminada |
Véase también
|
(C++11)
|
implementa un contenedor de propiedad de mutex movible
(plantilla de clase) |
|
(C++17)
|
contenedor RAII que evita interbloqueos para múltiples mutexes
(plantilla de clase) |