名前空間
変種
操作

std::lock_guard

From cppreference.com
< cpp‎ | thread
 
 
並行性サポートライブラリ
スレッド
(C++11)
(C++20)
this_thread 名前空間
(C++11)
(C++11)
(C++11)
協調的なキャンセル
排他制御
(C++11)
汎用ロック管理
(C++11)
lock_guard
(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 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は、デッドロック回避アルゴリズムを使用して複数のミューテックスをロックする機能を提供する、lock_guardの代替手段です。

(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>からの冗長な推論ガイドが提供されました。 削除

[編集] 関連項目

ムーブ可能なミューテックス所有権ラッパーを実装する
(クラステンプレート) [編集]
デッドロックを回避する、複数のミューテックス用のRAIIラッパー
(クラステンプレート) [編集]
English 日本語 中文(简体) 中文(繁體)