std:: lock_guard
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
|
ヘッダーで定義
<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 member function) |
|
lock_guard
オブジェクトを破棄し、基盤となるミューテックスをアンロックする
(public member function) |
|
|
operator=
[deleted]
|
コピー代入不可
(public member function) |
注記
初心者がよく犯す間違いは、
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ラッパー
(クラステンプレート) |