std::lock

来自cppreference.com
< cpp‎ | thread
定义于头文件 <mutex>
template< class Lockable1, class Lockable2, class... LockableN >
void lock( Lockable1& lock1, Lockable2& lock2, LockableN&... lockn );
(C++11 起)

锁定给定的可锁 (Lockable) 对象 lock1lock2...lockn ,使用免死锁算法避免死锁。

以对 locktry_lockunlock的未指定系列调用锁定对象。若对 lockunlock 的调用导致异常,则在重抛前对任何已锁的对象调用 unlock

目录

[编辑] 参数

lock1, lock2, ... , lockn - 要锁定的可锁 (Lockable) 对象

[编辑] 返回值

(无)

[编辑] 注意

Boost 提供此函数的一个版本,它接收以一对迭代器定义的可锁 (Lockable) 对象序列。

[编辑] 示例

下列示例用 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);
        {
            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 获得互斥的所有权
(函数模板) [编辑]