在視頻播放機程序中,常常採用這樣的架構:架構
一個負責讀文件的線程,負責從媒體文件中讀取數據並將數據包放入一個包隊列(queue),另外有多個線程從這個包隊列中取包並解碼,而後交給負責顯示的線程以便顯示圖像。因而,便造成了多個線程共享一個隊列,一個寫,多個只讀不寫的情形。函數
在不少時候,咱們都會遇到一個寫線程(負責寫數據),多個讀線程(負責讀數據)的情形。在這類情形下,固然能夠用鎖來保證每一個線程對共享數據的訪問是獨佔的。但這樣的作法在此情形下是低效的,由於它會使得一個讀線程在讀數據時另外的讀線程只能乾等着。ui
考慮到一個線程的對共享數據的讀不妨礙其餘線程的讀,咱們須要「讀寫鎖」這個東西。spa
設m爲一個讀寫鎖,那麼,當線程A對m上了寫鎖時,其餘線程便不能對m上讀鎖或寫鎖,直到A解開m的寫鎖;當一個線程B對m上了讀鎖時,其餘線程能夠對m上讀鎖,不能對m上寫鎖,直到B對m解開讀鎖。線程
1、初始化code
使用讀寫鎖以前,要定義一個SRWLOCK類型的變量:視頻
SRWLOCK rwm;
和臨界區同樣,rwm不能在代碼中修改讀取,對它的全部操做必須經過相關的函數來進行。隊列
用InitializeSRWLock函數初始化讀寫鎖,it
InitializeSRWLock(&rwm);
2、上鎖與解鎖class
// 上讀鎖 AcquireSRWLockShared(&rwm); // 解讀鎖 ReleaseSRWLockShared(&rwm); // 上寫鎖 AcquireSRWLockExclusive(&rwm); // 解寫鎖 ReleaseSRWLockExclusive(&rwm);
3、銷燬
讀寫鎖不須要手動銷燬。
4、封裝成類
爲了使用方便,我通常將其封裝成一個類,以達到「開箱即用」的效果。
頭文件:
class RWMutex { public: RWMutex(); ~RWMutex() = default; void RLock(); // 上讀鎖 void RUnlock(); // 解讀鎖 void Lock(); // 上寫鎖 void Unlock(); // 解寫鎖 private: SRWLOCK Lock_; private: RWMutex(const RWMutex&) = delete; void operator=(const RWMutex&) = delete; };
對應的源文件:
RWMutex::RWMutex() { ::InitializeSRWLock(&Lock_); } void RWMutex::RLock() { ::AcquireSRWLockShared(&Lock_); } void RWMutex::RUnlock() { ::ReleaseSRWLockShared(&Lock_); } void RWMutex::Lock() { ::AcquireSRWLockExclusive(&Lock_); } void RWMutex::Unlock() { ::ReleaseSRWLockExclusive(&Lock_); }