Namespaces
Variants

std:: lock_guard

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
(C++11)
lock_guard
(C++11)
(C++11)
(C++11)
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
ヘッダーで定義 <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 は、 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ラッパー
(クラステンプレート)