std::lock
定义于头文件 <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 <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 = "Employee " + id + " has lunch partners: "; for( const auto& partner : lunch_partners ) ret += partner + " "; return ret; } }; void send_mail(Employee &, Employee &) { // 模拟耗时的发信操作 std::this_thread::sleep_for(std::chrono::seconds(1)); } 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; } // 用 std::lock 获得二个锁,而不担心对 assign_lunch_partner 的其他调用会死锁我们 { 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); // 等价代码(若需要 unique_locks ,例如对于条件变量) // 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); // 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"); // 在平行线程指派,因为发邮件给用户告知午餐指派,会消耗长时间 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 christina and alice got locks dave and bob are waiting for locks dave and bob 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) |
试图通过重复调用 try_lock 获得互斥体的所有权 (函数模板) |
(C++17) |
用于多个互斥体的免死锁 RAII 封装器 (类模板) |