标签:
在视频播放机程序中,经常采用这样的架构:
一个负责读文件的线程,负责从媒体文件中读取数据并将数据包放入一个包队列(queue),另外有多个线程从这个包队列中取包并解码,然后交给负责显示的线程以便显示图像。于是,便形成了多个线程共享一个队列,一个写,多个只读不写的情形。
在很多时候,我们都会遇到一个写线程(负责写数据),多个读线程(负责读数据)的情形。在这类情形下,当然可以用锁来保证每个线程对共享数据的访问是独占的。但这样的做法在此情形下是低效的,因为它会使得一个读线程在读数据时另外的读线程只能干等着。
考虑到一个线程的对共享数据的读不妨碍其他线程的读,我们需要“读写锁”这个东西。
设m为一个读写锁,那么,当线程A对m上了写锁时,其他线程便不能对m上读锁或写锁,直到A解开m的写锁;当一个线程B对m上了读锁时,其他线程可以对m上读锁,不能对m上写锁,直到B对m解开读锁。
一、初始化
使用读写锁之前,要定义一个SRWLOCK类型的变量:
SRWLOCK rwm;
和临界区一样,rwm不能在代码中修改读取,对它的所有操作必须通过相关的函数来进行。
用InitializeSRWLock函数初始化读写锁,
InitializeSRWLock(&rwm);
二、上锁与解锁
// 上读锁 AcquireSRWLockShared(&rwm); // 解读锁 ReleaseSRWLockShared(&rwm); // 上写锁 AcquireSRWLockExclusive(&rwm); // 解写锁 ReleaseSRWLockExclusive(&rwm);
三、销毁
读写锁不需要手动销毁。
四、封装成类
为了使用方便,我一般将其封装成一个类,以达到开箱即用的效果。
头文件:
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_); }
标签:
原文地址:http://my.oschina.net/jthmath/blog/400781