在C++中,互斥鎖(Mutex)是用于線程同步的重要工具,用于保護共享資源,防止多線程同時訪問導致的數據競爭(Data Race)問題。
以下是C++中互斥鎖的核心用法和示例:
一、基本互斥鎖 std::mutex
1. 包含頭文件
#include <mutex>
2. 保護共享資源
std::mutex mtx; // 聲明互斥鎖
int shared_data = 0; // 共享資源void increment() {mtx.lock(); // 加鎖++shared_data; // 臨界區mtx.unlock(); // 解鎖
}
3. 使用 std::lock_guard
自動管理鎖
void safe_increment() {std::lock_guard<std::mutex> lock(mtx); // 構造時加鎖,析構時解鎖++shared_data; // 自動保護臨界區
} // 離開作用域時鎖自動釋放
二、遞歸互斥鎖 std::recursive_mutex
允許同一線程多次加鎖,避免死鎖:
std::recursive_mutex rmtx;void func1() {std::lock_guard<std::recursive_mutex> lock(rmtx);// 可以在此處再次加鎖func2();
}void func2() {std::lock_guard<std::recursive_mutex> lock(rmtx); // 同一線程可重入// ...
}
三、帶超時的互斥鎖 std::timed_mutex
std::timed_mutex tmtx;void try_lock_with_timeout() {// 嘗試加鎖,超時則放棄if (tmtx.try_lock_for(std::chrono::milliseconds(100))) {// 加鎖成功tmtx.unlock();} else {// 加鎖失敗}
}
四、讀寫鎖 std::shared_mutex
(C++17)
允許多個線程同時讀,但寫時獨占:
#include <shared_mutex> // C++17std::shared_mutex rw_mutex;
std::string shared_data;// 讀操作(共享鎖)
void reader() {std::shared_lock<std::shared_mutex> lock(rw_mutex);// 允許多個讀者同時訪問std::cout << shared_data << std::endl;
}// 寫操作(獨占鎖)
void writer() {std::unique_lock<std::shared_mutex> lock(rw_mutex);// 獨占訪問shared_data = "new data";
}
五、鎖的高級用法
1. 避免死鎖:使用 std::lock
同時鎖多個互斥鎖
std::mutex mtx1, mtx2;void safe_func() {// 原子性地鎖多個互斥鎖,避免死鎖std::lock(mtx1, mtx2);std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);// ...
}
2. 延遲加鎖 std::defer_lock
std::mutex mtx;void defer_lock_example() {std::unique_lock<std::mutex> lock(mtx, std::defer_lock);// 此時尚未加鎖// ...lock.lock(); // 手動加鎖// ...
}
六、常見錯誤與注意事項
-
忘記解鎖:
使用std::lock_guard
或std::unique_lock
自動管理鎖,避免手動lock/unlock
。 -
鎖粒度不當:
- 過大:性能下降(如鎖整個函數)。
- 過小:無法保護共享資源。
-
死鎖風險:
- 避免嵌套鎖。
- 確保所有線程以相同順序加鎖。
-
性能考量:
- 讀寫鎖(
std::shared_mutex
)適合讀多寫少的場景。 - 無鎖編程(Lock-Free)技術在高性能場景中更優。
- 讀寫鎖(
七、示例:線程安全的計數器
#include <mutex>
#include <thread>
#include <iostream>class Counter {
private:int value = 0;std::mutex mtx;public:void increment() {std::lock_guard<std::mutex> lock(mtx);++value;}int get() {std::lock_guard<std::mutex> lock(mtx);return value;}
};int main() {Counter counter;std::thread t1([&]() {for (int i = 0; i < 10000; ++i) {counter.increment();}});std::thread t2([&]() {for (int i = 0; i < 10000; ++i) {counter.increment();}});t1.join();t2.join();std::cout << "Final value: " << counter.get() << std::endl; // 輸出:20000return 0;
}
八、C++ 互斥鎖類型對比
類型 | 特性 | 適用場景 |
---|---|---|
std::mutex | 基本互斥鎖,不可重入 | 簡單互斥場景 |
std::recursive_mutex | 可重入鎖,允許同一線程多次加鎖 | 遞歸函數或嵌套鎖場景 |
std::timed_mutex | 支持超時的互斥鎖 | 需要嘗試加鎖并設置超時的場景 |
std::shared_mutex | 讀寫鎖,允許多讀一寫 | 讀多寫少的場景 |
合理選擇互斥鎖類型能有效提升代碼的安全性和性能。