名前空間
変種
操作

std::scoped_lock

提供: cppreference.com
< cpp‎ | thread
 
 
スレッドサポートライブラリ
スレッド
(C++11)
this_thread 名前空間
(C++11)
(C++11)
(C++11)
相互排他
(C++11)
汎用ロック管理
(C++11)
scoped_lock
(C++17)
(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... MutexTypes >
class scoped_lock;
(C++17以上)

クラス scoped_lock はスコープ付きブロックの期間に対して1つまたは複数のミューテックスを所有するための便利な RAII スタイルの仕組みを提供するミューテックスラッパーです。

scoped_lock オブジェクトが作成されると、指定されたミューテックスの所有権の取得が試みられます。 scoped_lock オブジェクトが作成されたスコープから制御が離れると、 scoped_lock は破棄され、ミューテックスは逆順で解放されます。 複数のミューテックスが指定された場合、 std::lock を使用したかのようにデッドロック回避アルゴリズムが使用されます。

scoped_lock クラスはコピー可能ではありません。

目次

[編集] テンプレート引数

MutexTypes - ロックするミューテックスの型。 Lockable の要件を満たさなければなりません。 ただし sizeof...(MutexTypes)==1 の場合は BasicLockable を満たすだけで構いません

[編集] メンバ型

メンバ型 定義
mutex_type (if sizeof...(MutexTypes)==1) ミューテックス。 MutexTypes... の唯一の型

[編集] メンバ関数

scoped_lock を構築し、オプションで指定したミューテックスをロックします
(パブリックメンバ関数) [edit]
scoped_lock オブジェクトを破壊し、ミューテックスのロックを解除します
(パブリックメンバ関数) [edit]
operator=
[削除]
コピー代入可能ではありません
(パブリックメンバ関数) [edit]

[編集]

以下の例は RAII スタイルでデッドロックせずに2個のミューテックスをロックするため std::scoped_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::scoped_lock to acquire two locks without worrying about 
        // other calls to assign_lunch_partner deadlocking us
        // and it also provides a convenient RAII-style mechanism
 
        std::scoped_lock lock(e1.m, e2.m);
 
        // Equivalent code 1 (using std::lock and std::lock_guard)
        // 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 2 (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);
        {
            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 alice are waiting for locks
dave and bob are waiting for locks
dave and bob got locks
christina and alice got locks
christina and bob got locks
Employee alice has lunch partners: bob christina 
Employee bob has lunch partners: alice dave christina 
Employee christina has lunch partners: alice bob 
Employee dave has lunch partners: bob

[編集] 欠陥報告

以下の動作変更欠陥報告は以前に発行された C++ 標準に遡って適用されました。

DR 適用先 発行時の動作 正しい動作
LWG 2981 C++17 scoped_lock<MutexTypes...> からの冗長な推定ガイドが提供されていました 削除されました

[編集] 関連項目

ムーブ可能なミューテックスの所有権のラッパーを実装します
(クラステンプレート) [edit]
厳密なスコープベースのミューテックス所有権のラッパーを実装します
(クラステンプレート) [edit]