首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++11 多線程核心技術深度解析:互斥鎖與死鎖防範

     編輯:關於C++

共享資料保護:互斥鎖的四大類型與最佳實踐

在多線程程式設計中,保護共享資料免受競態條件影響至關重要。C++11 標準庫(當時稱為 C++0x)提供了 std::mutex 系列互斥鎖,分為四種類型以滿足不同場景需求:

  • std::mutex:非遞歸互斥鎖,最輕量、最常用的基本鎖。
  • std::recursive_mutex:遞歸互斥鎖,允許同一線程多次鎖定,需配對相同次數的解鎖。
  • std::timed_mutex:支援超時機制的非遞歸鎖,可嘗試在指定時間內獲取鎖。
  • std::recursive_timed_mutex:結合遞歸與超時特性的互斥鎖。

RAII 鎖管理:lock_guard 與 unique_lock

C++ 採用 RAII(資源獲取即初始化)機制管理鎖的生命週期。兩大核心模板類別:

  • std::lock_guard:輕量級、不可移動、構造時鎖定、析構時自動解鎖,適合簡單的作用域鎖定。
  • std::unique_lock:功能更豐富,支援延遲鎖定(defer_lock)、超時嘗試鎖定、手動解鎖與所有權轉移,配合 timed_mutex 使用時威力最大。

程式碼範例:基本鎖定與超時控制

std::mutex m;
MyClass data;

void foo() {
    std::lock_guard<std::mutex> lk(m); // 自動鎖定/解鎖
    process(data);
} // 離開作用域自動解鎖

// 帶超時的鎖定嘗試
std::timed_mutex tm;
void timed_foo() {
    std::unique_lock<std::timed_mutex> lk(tm, std::chrono::milliseconds(3));
    if (lk) { // 成功獲取鎖
        process(data);
    }
} // 自動解鎖

死鎖防範:std::lock 多鎖原子獲取

當需要同時鎖定多個互斥量時,若各線程獲取順序不一致極易導致死鎖。C++11 提供 std::lock 一次性原子性地鎖定多個鎖,完全避免死鎖風險。

死鎖場景與解決方案

struct Account {
    std::mutex m;
    int balance;
};

void transfer(Account& a, Account& b) {
    // 使用 defer_lock 延遲鎖定
    std::unique_lock<std::mutex> lock_a(a.m, std::defer_lock);
    std::unique_lock<std::mutex> lock_b(b.m, std::defer_lock);
    
    // 原子性同時鎖定兩個互斥量
    std::lock(lock_a, lock_b);
    
    // 安全操作兩個帳戶資料
    // ...
}

若線程 1 執行 transfer(x, y) 而線程 2 執行 transfer(y, x),傳統逐個鎖定方式必然死鎖;使用 std::lock 則完全安全。

總結

掌握四種互斥鎖特性、善用 RAII 鎖管理類別、以及多鎖場景下的 std::lock,是編寫高效、安全 C++ 多線程程式的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved