名稱空間
變體
操作

std::lock_guard

來自 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)
期值
(C++11)
(C++11)
(C++11)
(C++11)
安全回收
(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,可選地鎖定給定的互斥體
(公共成員函式) [編輯]
銷燬lock_guard物件,解鎖底層互斥體
(公共成員函式) [編輯]
operator=
[已刪除]
不可複製賦值
(公共成員函式) [編輯]

[編輯] 注意

一個常見的初學者錯誤是“忘記”給lock_guard變數命名,例如std::lock_guard(mtx);(它預設構造一個名為mtxlock_guard變數)或std::lock_guard{mtx};(它構造一個prvalue物件,該物件立即被銷燬),從而實際上沒有構造一個在作用域剩餘時間內持有互斥體的鎖。

std::scoped_locklock_guard 提供了一個替代方案,它能夠使用死鎖避免演算法鎖定多個互斥體。

(C++17 起)

[編輯] 示例

演示了兩個執行緒對 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++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
LWG 2981 C++17 提供了冗餘的從 lock_guard<Mutex> 推導指南 已移除

[編輯] 另請參閱

實現可移動的互斥體所有權包裝器
(類模板) [編輯]
用於多個互斥體的死鎖避免 RAII 包裝器
(類模板) [編輯]