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 <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&) { // 模拟耗时的消息操作 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; } // 使用 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_lock,例如用于条件变量) // 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() <span class
参见
|
(C++11)
|
实现可移动的互斥量所有权包装器
(类模板) |
|
(C++11)
|
通过重复调用
try_lock
尝试获取互斥量所有权
(函数模板) |
|
(C++17)
|
避免死锁的多互斥量 RAII 包装器
(类模板) |