std::lock_guard
From cppreference.com
| ヘッダ <mutex> で定義 |
||
| template< class Mutex > class lock_guard; |
(C++11以降) | |
クラスlock_guardは、スコープブロックの期間中ミューテックスを所有するための便利なRAIIスタイルのメカニズムを提供するミューテックスラッパーです。
lock_guardオブジェクトが作成されると、与えられたミューテックスの所有権を取得しようとします。lock_guardオブジェクトが作成されたスコープから制御が離れると、lock_guardは破棄され、ミューテックスは解放されます。
lock_guardクラスはコピーできません。
目次 |
[編集] テンプレートパラメータ
| Mutex | - | ロックするミューテックスの型。この型はBasicLockable要件を満たす必要があります。 |
[編集] メンバ型
| メンバ型 | 定義 |
mutex_type
|
Mutex |
[編集] メンバ関数
lock_guardを構築し、オプションで指定されたミューテックスをロックします。(public メンバ関数) | |
lock_guardオブジェクトを破棄し、基礎となるミューテックスをアンロックします。(public メンバ関数) | |
| operator= [削除] |
コピー代入不可 (public メンバ関数) |
[編集] 注釈
初心者に多い間違いは、lock_guard変数に名前を「つけ忘れる」ことです。例えば、std::lock_guard(mtx); (これはmtxという名前のlock_guard変数をデフォルト構築します) や std::lock_guard{mtx}; (これはprvalueオブジェクトを構築し、すぐに破棄されます) のようにすると、実際にはスコープの残りの期間ミューテックスを保持するロックを構築しないことになります。
|
std::scoped_lockは、デッドロック回避アルゴリズムを使用して複数のミューテックスをロックする機能を提供する、 |
(C++17以降) |
[編集] 例
2つのスレッドによるvolatile変数の安全なインクリメントと安全でないインクリメントを示します。
このコードを実行
#include <iostream> #include <mutex> #include <string_view> #include <syncstream> #include <thread> volatile int g_i = 0; std::mutex g_i_mutex; // protects g_i void safe_increment(int iterations) { const std::lock_guard<std::mutex> lock(g_i_mutex); while (iterations-- > 0) g_i = g_i + 1; std::cout << "thread #" << std::this_thread::get_id() << ", g_i: " << g_i << '\n'; // g_i_mutex is automatically released when lock goes out of scope } void unsafe_increment(int iterations) { while (iterations-- > 0) g_i = g_i + 1; std::osyncstream(std::cout) << "thread #" << std::this_thread::get_id() << ", g_i: " << g_i << '\n'; } int main() { auto test = [](std::string_view fun_name, auto fun) { g_i = 0; std::cout << fun_name << ":\nbefore, g_i: " << g_i << '\n'; { std::jthread t1(fun, 1'000'000); std::jthread t2(fun, 1'000'000); } std::cout << "after, g_i: " << g_i << "\n\n"; }; test("safe_increment", safe_increment); test("unsafe_increment", unsafe_increment); }
実行結果の例
safe_increment: before, g_i: 0 thread #140121493231360, g_i: 1000000 thread #140121484838656, g_i: 2000000 after, g_i: 2000000 unsafe_increment: before, g_i: 0 thread #140121484838656, g_i: 1028945 thread #140121493231360, g_i: 1034337 after, g_i: 1034337
[編集] 欠陥報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 2981 | C++17 | lock_guard<Mutex>からの冗長な推論ガイドが提供されました。 |
削除 |
[編集] 関連項目
| (C++11) |
ムーブ可能なミューテックス所有権ラッパーを実装する (クラステンプレート) |
| (C++17) |
デッドロックを回避する、複数のミューテックス用のRAIIラッパー (クラステンプレート) |