名前空間
変種
操作

std::lock

From cppreference.com
< cpp‎ | thread
 
 
並行性サポートライブラリ
スレッド
(C++11)
(C++20)
this_thread 名前空間
(C++11)
(C++11)
(C++11)
協調的なキャンセル
排他制御
(C++11)
汎用ロック管理
lock
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
条件変数
(C++11)
セマフォ
ラッチとバリア
(C++20)
(C++20)
future
(C++11)
(C++11)
(C++11)
(C++11)
安全なメモリ解放 (Safe Reclamation)
(C++26)
ハザードポインタ
アトミック型
(C++11)
(C++20)
アトミック型の初期化
(C++11)(C++20で非推奨)
(C++11)(C++20で非推奨)
メモリオーダー
(C++11)(C++26で非推奨)
アトミック操作のためのフリー関数
アトミックフラグのためのフリー関数
 
ヘッダ <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)
try_lockの繰り返し呼び出しによってミューテックスの所有権を取得しようと試みる
(関数テンプレート) [編集]
デッドロックを回避する、複数のミューテックス用のRAIIラッパー
(クラステンプレート) [編集]
English 日本語 中文(简体) 中文(繁體)