【UE4源代码分析】-004 读写锁

1、读写锁

  在上一篇中讨论临界区时,我们发现临界区虽然实现了对临界资源的保护,但同时也使所有对临界资源的访问都变成了串行的请求。实际上,线程请求临界资源之后可以分成两种行为,一种是读操作,另一种是写操作。当多个读操作同时进行时,不会发生资源被修改的问题,多个读操作时可以并行进行的。但多个写操作或者写操作和读操作之间,由于可能在写操作的过程中发生中断行为,或者读操作的过程中发生中断,导致数据被写操作修改,因此,多个写操作或写操作与读操作之间不能同时进行。
  为了使多个读操作能够并行处理同时保持写操作的独占性,产生了读写锁。
  在Vista之后,windows系统中出现了SRWLock对象。SRWLock是微软对读写锁的一个实现方案。

2、windows读写锁

  我们先来看一看MSDN上微软对SRWLock的描述。

Slim Reader/Writer (SRW) Locks

Slim reader/writer (SRW) locks enable the threads of a single process to access shared resources; they are optimized for speed and occupy very little memory. Slim reader-writer locks cannot be shared across processes.

Reader threads read data from a shared resource whereas writer threads write data to a shared resource. When multiple threads are reading and writing using a shared resource, exclusive locks such as a critical section or mutex can become a bottleneck if the reader threads run continuously but write operations are rare.

SRW locks provide two modes in which threads can access a shared resource:

Shared mode, which grants shared read-only access to multiple reader threads, which enables them to read data from the shared resource concurrently. If read operations exceed write operations, this concurrency increases performance and throughput compared to critical sections.
Exclusive mode, which grants read/write access to one writer thread at a time. When the lock has been acquired in exclusive mode, no other thread can access the shared resource until the writer releases the lock.

A single SRW lock can be acquired in either mode; reader threads can acquire it in shared mode whereas writer threads can acquire it in exclusive mode. There is no guarantee about the order in which threads that request ownership will be granted ownership; SRW locks are neither fair nor FIFO.

An SRW lock is the size of a pointer. The advantage is that it is fast to update the lock state. The disadvantage is that very little state information can be stored, so SRW locks cannot be acquired recursively. In addition, a thread that owns an SRW lock in shared mode cannot upgrade its ownership of the lock to exclusive mode.

The caller must allocate an SRWLOCK structure and initialize it by either calling InitializeSRWLock (to initialize the structure dynamically) or assign the constant SRWLOCK_INIT to the structure variable (to initialize the structure statically).

The following are the SRW lock functions.

SRW lock function Description
AcquireSRWLockExclusive Acquires an SRW lock in exclusive mode.
AcquireSRWLockShared Acquires an SRW lock in shared mode.
InitializeSRWLock Initialize an SRW lock.
ReleaseSRWLockExclusive Releases an SRW lock that was opened in exclusive mode.
ReleaseSRWLockShared Releases an SRW lock that was opened in shared mode.
SleepConditionVariableSRW Sleeps on the specified condition variable and releases the specified lock as an atomic operation.
TryAcquireSRWLockExclusive Attempts to acquire a slim reader/writer (SRW) lock in exclusive mode. If the call is successful, the calling thread takes ownership of the lock.
TryAcquireSRWLockShared Attempts to acquire a slim reader/writer (SRW) lock in shared mode. If the call is successful, the calling thread takes ownership of the lock.

  从上面的介绍可以看出,SRWLock只能用于单个进程的多个线程之间进行资源同步,不能用于多个进程间的资源同步。SRWLock将线程分为两中模式——共享模式和独占模式。共享模式允许多个读线程同时对临界资源进行访问,当读线程数目比写线程多时,SRWLock与临界区相比,具有更高的效率。独占模式下,线程将独占临界资源,当临界资源处于独占模式下时,其余线程不能访问临界资源直到写线程结束对资源的访问。
  SRWLock本身不提供优先级判断,既不是公平锁也不是FIFO。
  SRWLock的大小仅仅为一个指针大小,好处是能够高效地改变锁的状态,坏处是只能保存少量的锁的状态信息。所以SRWLock锁不能被递归获取,并且已经使用共享模式获取锁的线程也不能修改自己的状态到独占模式。
  使用上表中所列出的接口函数,用户可以创建读写锁,并对读写锁进行共享模式和独占模式的加锁与释放操作。
  注意,系统并没有提供销毁读写锁的接口。

3、UE4中的读写锁

  UE中,对Windows提供的读写锁进行了封装,提供了FWindowsRWLock类。

/**
 * FWindowsRWLock - Read/Write Mutex
 *	- Provides non-recursive Read/Write (or shared-exclusive) access.
 *	- Windows specific lock structures/calls Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/aa904937(v=vs.85).aspx
 */
class FWindowsRWLock
{
public:
	FORCEINLINE FWindowsRWLock(uint32 Level = 0)
	{
		Windows::InitializeSRWLock(&Mutex);
	}
	
	FORCEINLINE ~FWindowsRWLock()
	{
	}
	//共享模式加锁
	FORCEINLINE void ReadLock()
	{
		Windows::AcquireSRWLockShared(&Mutex);
	}
	//独占模式加锁
	FORCEINLINE void WriteLock()
	{
		Windows::AcquireSRWLockExclusive(&Mutex);
	}
	//共享模式解锁
	FORCEINLINE void ReadUnlock()
	{
		Windows::ReleaseSRWLockShared(&Mutex);
	}
	//独占模式解锁
	FORCEINLINE void WriteUnlock()
	{
		Windows::ReleaseSRWLockExclusive(&Mutex);
	}
	
private:
	Windows::SRWLOCK Mutex;
};

  从上面的实现可以看出,FWindowsRWLock类是对Windows::SRWLOCK的封装,并提供了创建(FWindowsRWLock())接口,共享模式操作(FORCEINLINE void ReadLock()共享模式加锁,FORCEINLINE void ReadUnlock()共享模式解锁)接口,独占模式操作(FORCEINLINE void WriteLock()独占模式加锁,FORCEINLINE void WriteUnlock()独占模式解锁)接口。
  从使用上来看,FWindowsRWLock在对象构造的时候创建windows::SRWLock,之后的操作都通过封装的接口操作。

你可能感兴趣的:(UE4)