讀寫鎖是一種特殊的鎖機制,允許多個執行緒同時讀取共享資料,但在寫入共享資料時,只有一個執行緒可以進行寫操作,其他執行緒必須等待。
這種機制對於讀多寫少的場景非常有效,可以提高併發效能。以下是透過 shared_lock
、unique_lock
、shared_mutex
和 mutex
的解釋來說明讀寫鎖的實現和應用。
1. 基本概念
-
讀鎖(Shared Lock):
- 使用
shared_lock
加鎖,允許多個執行緒同時持有讀鎖,這樣它們可以併發地讀取共享資料。 - 在持有讀鎖的情況下,其他執行緒仍然可以獲取讀鎖,但無法獲取寫鎖。
- 使用
-
寫鎖(Exclusive Lock):
- 使用
unique_lock
加鎖,只有一個執行緒可以持有寫鎖。持有寫鎖的執行緒在寫入資料時,其他執行緒無法獲取任何型別的鎖(無論是讀鎖還是寫鎖)。 - 寫鎖的目的在於保證資料的安全性和一致性。
- 使用
2. shared_mutex
與 mutex
-
shared_mutex
:- 是 C++14 引入的一個互斥體型別,專門用於支援讀寫鎖。
-** 它支援共享鎖(透過shared_lock
)和獨佔鎖(透過unique_lock
)**。透過這種方式,多個執行緒可以安全地讀取資料,而在寫入資料時,可以保證只有一個執行緒在寫。
- 是 C++14 引入的一個互斥體型別,專門用於支援讀寫鎖。
-
mutex
:- 是最基本的互斥體,提供了互斥訪問共享資源的功能。
- 使用
mutex
時,如果一個執行緒持有鎖,其他執行緒都無法訪問受保護的資源。
3. 示例程式碼
以下是一個示例,展示瞭如何使用 shared_mutex
、shared_lock
和 unique_lock
實現一個簡單的讀寫鎖:
#include <iostream>
#include <thread>
#include <shared_mutex>
#include <vector>
#include <chrono>
class SharedData {
private:
int data;
mutable std::shared_mutex mutex;
public:
SharedData() : data(0) {}
// 讀操作
int read() const {
std::shared_lock<std::shared_mutex> lock(mutex); // 共享鎖
return data;
}
// 寫操作
void write(int value) {
std::unique_lock<std::shared_mutex> lock(mutex); // 獨佔鎖
data = value;
}
};
// 讀執行緒函式
void reader(SharedData& shared_data, int id) {
for (int i = 0; i < 5; ++i) {
std::cout << "Reader " << id << " reads: " << shared_data.read() << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
// 寫執行緒函式
void writer(SharedData& shared_data, int value) {
for (int i = 0; i < 5; ++i) {
shared_data.write(value);
std::cout << "Writer writes: " << value << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(300));
value++; // 增加寫入值
}
}
int main() {
SharedData shared_data;
// 建立讀執行緒
std::vector<std::thread> readers;
for (int i = 0; i < 3; ++i) {
readers.emplace_back(reader, std::ref(shared_data), i);
}
// 建立寫執行緒
std::thread writer_thread(writer, std::ref(shared_data), 0);
// 等待執行緒完成
for (auto& r : readers) {
r.join();
}
writer_thread.join();
return 0;
}
4. 解釋
-
共享讀取:
- 在
read
方法中,使用shared_lock
來加鎖。這允許多個執行緒同時讀取data
,因為它們不會阻塞彼此。
- 在
-
獨佔寫入:
- 在
write
方法中,使用unique_lock
來加鎖。這保證了在寫入資料時,其他執行緒不能讀取或寫入。
- 在
-
執行緒安全:
- 透過使用
shared_mutex
,確保在讀取時允許併發訪問,而在寫入時則獨佔訪問,有效提高了程式的併發效能。
- 透過使用
總結
讀寫鎖是提高讀多寫少場景下效能的有效機制。透過使用 shared_mutex
、shared_lock
和 unique_lock
,可以實現安全的併發訪問,確保資料的一致性和正確性。這種方式在多執行緒程式設計中是非常常見的,特別是在需要頻繁讀取而寫入相對較少的應用中。