std::lock
De cppreference.com
Definido en el archivo de 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
usando un algoritmo de evitación de bloqueo mutuo para evitar el bloqueo mutuo. Los objetos se bloquean por una serie de llamadas no especificadas a lock
, try_lock
, y unlock
. Si una llamada a lock
o unlock
resulta en una excepción, se llama a unlock
por cualquiera de los objetos bloqueados antes de volver a lanzar.
Contenido |
[editar]Parámetros
lock1, lock2, ... , lockn | - | Los objetos Lockable a bloquear. |
[editar]Valor de retorno
(none)
[editar]Notas
Boost proporciona una versión de esta función que toma una secuencia de objetos Lockable definidos por un par de iteradores.
std::scoped_lock ofrece un envoltorio RAII para esta función, y se prefiere generalmente a una llamada manifiesta a std::lock
.
[editar]Ejemplo
El siguiente ejemplo utiliza a std::lock
para bloquear pares de mutexes sin bloqueo mutuo.
Ejecuta este código
#include <mutex>#include <thread>#include <iostream>#include <vector>#include <functional>#include <chrono>#include <string> 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(a) "+ id +" tiene compañeros para el almuerzo: ";for(constauto& partner : lunch_partners ) ret += partner +" ";return ret;}}; void send_mail(Employee &, Employee &){// simular una operación de mensajeo de largo tiempostd::this_thread::sleep_for(std::chrono::seconds(1));} void assign_lunch_partner(Employee &e1, Employee &e2){staticstd::mutex io_mutex;{std::lock_guard<std::mutex> lk(io_mutex);std::cout<< e1.id<<" and "<< e2.id<<" están a la espera de cerrojos"<<std::endl;} // usar std::lock para adquirir dos cerrojos sin preocuparse de// otras llamadas a assign_lunch_partner que nos bloqueen mutuamente{ 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 code (si se necesitan unique_locks, es decir, 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);// Solución superior disponible en 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<<" obtuvieron cerrojos"<<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 ana("Ana"), beto("Beto"), cristina("Cristina"), david("David"); // asignar en hilos paralelos ya que enviar correo a usuarios sobre// las asignaciones de los compañeros de almuerzo toma mucho tiempostd::vector<std::thread> threads; threads.emplace_back(assign_lunch_partner, std::ref(Ana), std::ref(Beto)); threads.emplace_back(assign_lunch_partner, std::ref(Cristina), std::ref(Beto)); threads.emplace_back(assign_lunch_partner, std::ref(Cristina), std::ref(Ana)); threads.emplace_back(assign_lunch_partner, std::ref(David), std::ref(Beto)); for(auto&thread : threads) thread.join();std::cout<< ana.output()<<'\n'<< beto.output()<<'\n'<< cristina.output()<<'\n'<< david.output()<<'\n';}
Posible salida:
Ana y Beto están a la espera de cerrojos Ana y Beto obtuvieron cerrojos Cristina y Beto están a la espera de cerrojos Cristina y Beto obtuvieron cerrojos Cristina y Ana están a la espera de cerrojos Cristina y Ana obtuvieron cerrojos David y Beto están a la espera de cerrojos David y Beto obtuvieron cerrojos Empleado(a) Ana tiene compañeros para el almuerzo: Beto Cristina Empleado(a) Beto tiene compañeros para el almuerzo: Ana Cristina David Empleado(a) Cristina tiene compañeros para el almuerzo: Beto Ana Empleado(a) David tiene compañeros para el almuerzo: Beto
[editar]Véase también
(C++11) | Intenta tomar posesión de los mutex mediante llamadas repetidas a try_lock . (plantilla de función) |
(C++17) | Envoltorio RAII que evita bloqueo mutuo para múltiples mutex. (plantilla de clase) |