名前空間
変種
操作

std::lock

提供: cppreference.com
< cpp‎ | thread
 
 
スレッドサポートライブラリ
スレッド
(C++11)
this_thread 名前空間
(C++11)
(C++11)
(C++11)
相互排他
(C++11)
汎用ロック管理
(C++11)
lock
(C++11)
(C++11)
(C++11)(C++11)(C++11)
(C++11)
(C++11)
条件変数
(C++11)
フューチャー
(C++11)
(C++11)
(C++11)
(C++11)
 
ヘッダ <mutex> で定義
template< class Lockable1, class Lockable2, class... LockableN >
void lock( Lockable1& lock1, Lockable2& lock2, LockableN&... lockn );
(C++11およびそれ以降)

デッドロックを回避するためにデッドロック回避アルゴリズムを使用して、指定された Lockable なオブジェクト lock1, lock2, ..., lockn をロックします。

オブジェクトは未規定の一連の locktry_lockunlock の呼び出しによってロックされます。 lock または unlock の呼び出しで例外が発生した場合、再スローの前にロックされたすべてのオブジェクトに対して unlock が呼ばれます。

目次

[編集] 引数

lock1, lock2, ... , lockn - ロックする Lockable なオブジェクト

[編集] 戻り値

(なし)

[編集] ノート

イテレータの組によって定義される一連の Lockable オブジェクトを取るバージョンのこの関数が boost で提供されています

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 &)
{
    // simulate a time-consuming messaging operation
    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;
    }
 
    // 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
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 を繰り返し呼び出して複数のミューテックスの所有権の取得を試みます
(関数テンプレート) [edit]
複数のミューテックスに対するデッドロック回避機能付きの RAII ラッパー
(クラステンプレート) [edit]