std::lock
來自 cppreference.com
定義於標頭檔案 <mutex> |
||
template< class Lockable1, class Lockable2, class... LockableN > void lock( Lockable1& lock1, Lockable2& lock2, LockableN&... lockn ); |
(C++11 起) | |
使用死鎖避免演算法鎖定給定的 Lockable 物件 lock1、lock2、...
、lockn 以避免死鎖。
這些物件透過一系列未指定的 lock
、try_lock
和 unlock
呼叫來鎖定。如果對 lock
或 unlock
的呼叫導致異常,則在重新丟擲之前,會對所有已鎖定的物件呼叫 unlock
。
目錄 |
[編輯] 引數
lock1, lock2, ... , lockn | - | 要鎖定的 Lockable 物件 |
[編輯] 返回值
(無)
[編輯] 注意
Boost 提供此函式的一個版本,它接受一對迭代器定義的 Lockable 物件序列。
std::scoped_lock 為此函式提供了 RAII 包裝器,通常優於直接呼叫 std::lock
。
[編輯] 示例
以下示例使用 std::lock
鎖定成對的互斥量而不會發生死鎖。
執行此程式碼
#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 = "Employee " + id + " has lunch partners: "; for (auto n{lunch_partners.size()}; const auto& partner : lunch_partners) ret += partner + (--n ? ", " : ""); return ret; } }; void send_mail(Employee&, Employee&) { // Simulate a time-consuming messaging operation 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 << " and " << e2.id << " are waiting for locks" << std::endl; } // Use std::lock to acquire two locks without worrying about // other calls to assign_lunch_partner deadlocking us { 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); // Equivalent code (if unique_locks are needed, e.g. for condition variables) // 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 << " and " << e2.id << " got locks" << 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"); // Assign in parallel threads because mailing users about lunch assignments // takes a long time 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'; }
可能的輸出
Alice and Bob are waiting for locks Alice and Bob got locks Christina and Bob are waiting for locks Christina and Bob got locks Christina and Alice are waiting for locks Dave and Bob are waiting for locks Dave and Bob got locks Christina and Alice got locks Employee Alice has lunch partners: Bob, Christina Employee Bob has lunch partners: Alice, Christina, Dave Employee Christina has lunch partners: Bob, Alice Employee Dave has lunch partners: Bob
[編輯] 參閱
(C++11) |
實現可移動的互斥體所有權包裝器 (類模板) |
(C++11) |
嘗試透過重複呼叫 try_lock 來獲取互斥體的所有權(函式模板) |
(C++17) |
用於多個互斥體的死鎖避免 RAII 包裝器 (類模板) |