關于讀寫鎖,有個線程在讀,能寫嗎?有個線程在寫,能讀嗎?
引言
在多線程編程中,讀寫鎖(Read-Write Lock)是一種常見的同步機制,用于解決多個線程同時訪問共享資源的問題。
讀寫鎖
讀-寫問題分析
在回答上述問題之前,我們需要理解兩種不同類型的線程操作:讀操作和寫操作。
讀操作是無副作用的操作,它只從共享資源中獲取信息而不改變其狀態。
寫操作是有副作用的操作,它會修改共享資源的狀態。
當有多個線程同時訪問共享資源時,我們需要確保以下幾點:
一致性:所有線程看到的數據是一致的。
原子性:復合操作被視為不可分割的整體,要么全部完成,要么全部不發生。
隔離性:線程間的操作相互獨立,不會互相干擾。
持久性:一旦寫操作完成,結果必須持久化,即使系統崩潰也能恢復。
讀寫鎖是一種特殊的鎖機制,它把對共享資源的訪問分為讀操作和寫操作:
讀操作(共享鎖):允許多個線程同時讀取資源,如果當前沒有寫者,讀鎖可以被多個讀者持有。當有寫者嘗試獲取鎖時,所有新的讀請求都會被阻塞,直到寫者釋放了鎖。
寫操作(排他鎖):只允許一個線程寫入資源,寫鎖是排他的,當一個線程持有寫鎖時,其他任何線程(無論是讀者還是寫者)都不能訪問資源。只有當寫鎖被釋放后,其他線程才能繼續。
讀寫鎖的規則:
讀-讀:允許并發
讀-寫:互斥
寫-讀:互斥
寫-寫:互斥
C++讀寫鎖實現
C++17引入了std::shared_mutex,這是標準庫提供的讀寫鎖實現:
#include <shared_mutex>
#include <thread>
#include <iostream>
#include <vector>
#include <chrono>
class ThreadSafeCounter {
private:
mutable std::shared_mutex mutex_;
int value_ = 0;
public:
// 寫操作 - 使用獨占鎖
void increment() {
std::unique_lock<std::shared_mutex> lock(mutex_);
value_++;
}
// 讀操作 - 使用共享鎖
int get() const {
std::shared_lock<std::shared_mutex> lock(mutex_);
return value_;
}
};
在這個例子中,std::shared_lock 用于保護讀操作,而 std::unique_lock 用于保護寫操作。讀者可以同時訪問共享數據,而寫者則需要獨占訪問。
結論
有個線程在讀,能寫嗎?不能。如果有線程正在讀取數據,那么寫操作應該被推遲,直到所有的讀操作完成。這是為了確保寫操作不會破壞讀者看到的一致性視圖。
有個線程在寫,能讀嗎?也不能。如果一個線程正在寫入數據,那么所有其他線程(包括讀者和寫者)都必須等待,直到寫操作完成。這是為了確保寫操作的原子性和隔離性。