std:: lock
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Défini dans l'en-tête
<mutex>
|
||
|
template
<
class
Lockable1,
class
Lockable2,
class
...
LockableN
>
void lock ( Lockable1 & lock1, Lockable2 & lock2, LockableN & ... lockn ) ; |
(depuis C++11) | |
Verrouille les objets
Lockable
donnés
lock1
,
lock2
,
...
,
lockn
en utilisant un algorithme d'évitement des interblocages pour prévenir les deadlocks.
Les objets sont verrouillés par une série non spécifiée d'appels à
lock
,
try_lock
, et
unlock
. Si un appel à
lock
ou
unlock
provoque une exception,
unlock
est appelé pour tous les objets verrouillés avant de relancer l'exception.
Table des matières |
Paramètres
| lock1, lock2, ... , lockn | - | les Lockable objets à verrouiller |
Valeur de retour
(aucun)
Notes
Boost fournit une version de cette fonction qui prend une séquence d'objets Lockable définie par une paire d'itérateurs.
std::scoped_lock
offre une
RAII
enveloppe pour cette fonction, et est généralement préféré à un appel direct à
std::lock
.
Exemple
L'exemple suivant utilise
std::lock
pour verrouiller des paires de mutex sans interblocage.
#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 = "Employé " + id + " a des partenaires de déjeuner: "; for (auto n{lunch_partners.size()}; const auto& partner : lunch_partners) ret += partner + (--n ? ", " : ""); return ret; } }; void send_mail(Employee&, Employee&) { // Simuler une opération de messagerie longue 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 << " et " << e2.id << " attendent des verrous" << std::endl; } // Utiliser std::lock pour acquérir deux verrous sans se soucier de // autres appels à assign_lunch_partner nous bloquant { 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); // Code équivalent (si des verrous uniques sont nécessaires, par exemple pour des variables de condition) // 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); // Solution supérieure disponible en C++17 // std::scoped_lock lk(e1.m, e2.m); { std::lock_guard<std::mutex> lk(io_mutex); std::cout << e1.id << " et " << e2.id << " a obtenu des verrous" << 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"); // Assigner en parallèle dans des threads car envoi d'emails aux utilisateurs concernant les affectations de déjeuner // prend beaucoup de temps 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'; }
Sortie possible :
Alice et Bob attendent les verrous Alice et Bob ont obtenu les verrous Christina et Bob attendent les verrous Christina et Bob ont obtenu les verrous Christina et Alice attendent les verrous Dave et Bob attendent les verrous Dave et Bob ont obtenu les verrous Christina et Alice ont obtenu les verrous Employé Alice a des partenaires de déjeuner : Bob, Christina Employé Bob a des partenaires de déjeuner : Alice, Christina, Dave Employé Christina a des partenaires de déjeuner : Bob, Alice Employé Dave a des partenaires de déjeuner : Bob
Voir aussi
|
(C++11)
|
implémente un wrapper de propriété de mutex déplaçable
(modèle de classe) |
|
(C++11)
|
tente d'obtenir la propriété des mutex via des appels répétés à
try_lock
(modèle de fonction) |
|
(C++17)
|
wrapper RAII évitant les interblocages pour plusieurs mutex
(modèle de classe) |