std:: lock
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Definido en el encabezado
<mutex>
|
||
|
template
<
class
Lockable1,
class
Lockable2,
class
...
LockableN
>
void lock ( Lockable1 & lock1, Lockable2 & lock2, LockableN & ... lockn ) ; |
(desde C++11) | |
Bloquea los objetos
Lockable
dados
lock1
,
lock2
,
...
,
lockn
utilizando un algoritmo de prevención de interbloqueos para evitar el deadlock.
Los objetos están bloqueados por una serie no especificada de llamadas a
lock
,
try_lock
, y
unlock
. Si una llamada a
lock
o
unlock
resulta en una excepción,
unlock
es llamado para cualquier objeto bloqueado antes de relanzarla.
Contenidos |
Parámetros
| lock1, lock2, ... , lockn | - | los Lockable objetos a bloquear |
Valor de retorno
(ninguno)
Notas
Boost proporciona una versión de esta función que toma una secuencia de Lockable objetos definidos por un par de iteradores.
std::scoped_lock
ofrece un
RAII
wrapper para esta función, y generalmente se prefiere sobre una llamada directa a
std::lock
.
Ejemplo
El siguiente ejemplo utiliza
std::lock
para bloquear pares de mutexes sin interbloqueo.
#include <chrono> #include <functional> #include <iostream> #include <mutex> #include <string> #include <thread> #include <vector> struct Employee { Employee(std::string id) : id(id) {} std::string id; std::vector<std::string> lunch_partners; std::mutex m; std::string output() const { std::string ret = "Empleado " + id + " tiene compañeros de almuerzo: "; for (auto n{lunch_partners.size()}; const auto& partner : lunch_partners) ret += partner + (--n ? ", " : ""); return ret; } }; void send_mail(Employee&, Employee&) { // Simular una operación de mensajería que consume tiempo std::this_thread::sleep_for(std::chrono::milliseconds(696)); } void assign_lunch_partner(Employee& e1, Employee& e2) { static std::mutex io_mutex; { std::lock_guard<std::mutex> lk(io_mutex); std::cout << e1.id << " y " << e2.id << " están esperando por bloqueos" << std::endl; } // Use std::lock to acquire two locks without worrying about // otras llamadas a assign_lunch_partrier nos bloquean { std::lock(e1.m, e2.m); std::lock_guard<std::mutex> lk1(e1.m, std::adopt_lock); std::lock_guard<std::mutex> lk2(e2.m, std::adopt_lock); // Código equivalente (si se necesitan unique_locks, por ejemplo para variables de condición) // std::unique_lock<std::mutex> lk1(e1.m, std::defer_lock); // std::unique_lock<std::mutex> lk2(e2.m, std::defer_lock); // std::lock(lk1, lk2); // Superior solution available in C++17 // std::scoped_lock lk(e1.m, e2.m); { std::lock_guard<std::mutex> lk(io_mutex); std::cout << e1.id << " y " << e2.id << " obtuvo bloqueos" << std::endl; } e1.lunch_partners.push_back(e2.id); e2.lunch_partners.push_back(e1.id); } send_mail(e1, e2); send_mail(e2, e1); } int main() { Employee alice("Alice"), bob("Bob"), christina("Christina"), dave("Dave"); // Asignar en hilos paralelos porque enviar correo a usuarios sobre asignaciones de almuerzo // toma mucho tiempo std::vector<std::thread> threads; threads.emplace_back(assign_lunch_partner, std::ref(alice), std::ref(bob)); threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(bob)); threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(alice)); threads.emplace_back(assign_lunch_partner, std::ref(dave), std::ref(bob)); for (auto& thread : threads) thread.join(); std::cout << alice.output() << '\n' << bob.output() << '\n' << christina.output() << '\n' << dave.output() << '\n'; }
Salida posible:
Alice y Bob están esperando por locks Alice y Bob obtuvieron locks Christina y Bob están esperando por locks Christina y Bob obtuvieron locks Christina y Alice están esperando por locks Dave y Bob están esperando por locks Dave y Bob obtuvieron locks Christina y Alice obtuvieron locks Empleado Alice tiene compañeros de almuerzo: Bob, Christina Empleado Bob tiene compañeros de almuerzo: Alice, Christina, Dave Empleado Christina tiene compañeros de almuerzo: Bob, Alice Empleado Dave tiene compañeros de almuerzo: Bob
Véase también
|
(C++11)
|
implementa un contenedor de propiedad de mutex móvil
(plantilla de clase) |
|
(C++11)
|
intenta obtener la propiedad de mutexes mediante llamadas repetidas a
try_lock
(plantilla de función) |
|
(C++17)
|
contenedor RAII que evita interbloqueos para múltiples mutexes
(plantilla de clase) |