Visual C++ 7.1Visual C++ 8.0Visual C++ 7.0C++/CLIVisual Studio 2005Windows 2000Visual C++ 6.0高级Windows XP开发Visual StudioWindowsC++.NET
适用于 Windows 的超简单 C++ 读/写锁类
在 C++ 中实现超简单的读/写锁模式。
引言
CReadWriteLock
类是一个非常简单的类,它实现了读者/写者模式,用于同步对共享资源的多个线程访问。 通过允许多个读者访问或单个写者访问,该类比标准同步机制(如临界区)提供更高的吞吐量。
背景
在网上寻找简单的解决方案时,我发现许多解决方案过于复杂,并且没有遵循 KISS(保持简单,傻瓜)原则。 因此,我决定实现一个简单但实用的解决方案。
请注意,为了防止读者饥饿,CReadWriteLock
仅应在读者访问远比写者访问更常见时使用。 这是因为该实现不包含任何线程队列或类似机制来保证访问顺序,并且写者线程将始终赢得这场竞争。
使用代码
只需将类(ReadWriteLock.cpp 和 ReadWriteLock.h)复制到项目文件夹中,并将这两个文件添加到项目中即可。
代码几乎不言自明;创建一个 CReadWriteLock
实例,并在使用共享资源之前分别使用 LockReader()
/UnlockReader()
和 LockWriter()
/UnlockWriter()
。
ReadWriteLock.h
##pragma once
#include "Windows.h"
class CReadWriteLock
{
public:
//! Constructor.
CReadWriteLock(void);
//! Destructor.
virtual ~CReadWriteLock(void);
//! Lock for reader access.
void LockReader();
//! Unlock reader access.
void UnlockReader();
//! Lock for writer access.
void LockWriter();
//! Unlock writer access.
void UnlockWriter();
private:
//! Private copy constructor.
CReadWriteLock(const CReadWriteLock &cReadWriteLock);
//! Private assignment operator.
const CReadWriteLock& operator=(const CReadWriteLock &cReadWriteLock);
//! Increment number of readers.
void IncrementReaderCount();
//! Decrement number of readers.
void DecrementReaderCount();
//! Writer access event.
HANDLE m_hWriterEvent;
//! No readers event.
HANDLE m_hNoReadersEvent;
//! Number of readers.
int m_nReaderCount;
//! Critical section for protecting lock writer method.
CRITICAL_SECTION m_csLockWriter;
//! Critical section for protecting reader count.
CRITICAL_SECTION m_csReaderCount;
};
ReadWriteLock.cpp
#include "StdAfx.h"
#include "ReadWriteLock.h"
CReadWriteLock::CReadWriteLock(void)
: m_nReaderCount(0), m_hWriterEvent(NULL), m_hNoReadersEvent(NULL)
{
// Create writer event with manual reset and default signaled state.
//
// State:
// Signaled = Writer has currently not access.
// Non-signaled = Writer has currently access, block readers.
//
m_hWriterEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
// Create no readers event with manual reset and default signaled state.
//
// State:
// Signaled = No readers have currently access.
// Non-signaled = Some readers have currently access, block writer.
//
m_hNoReadersEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
//
// Initialize critical sections.
InitializeCriticalSection(&m_csLockWriter);
InitializeCriticalSection(&m_csReaderCount);
}
CReadWriteLock::CReadWriteLock(const CReadWriteLock &cReadWriteLock)
{
}
const CReadWriteLock& CReadWriteLock::operator=(const CReadWriteLock &cReadWriteLock)
{
return *this;
}
CReadWriteLock::~CReadWriteLock(void)
{
//
// Delete critical sections.
DeleteCriticalSection(&m_csLockWriter);
DeleteCriticalSection(&m_csReaderCount);
// Close the writer event.
CloseHandle(m_hWriterEvent);
// Close the no readers event.
CloseHandle(m_hNoReadersEvent);
}
void CReadWriteLock::LockReader()
{
bool bLoop = true;
// Loop.
while(bLoop)
{
// Wait for Writer event to be signaled.
WaitForSingleObject(m_hWriterEvent, INFINITE);
// Increment number of readers.
IncrementReaderCount();
// If writer is become non-signaled fall back (double locking).
if(WaitForSingleObject(m_hWriterEvent, 0) != WAIT_OBJECT_0)
{
// Decrement number of readers.
DecrementReaderCount();
}
else
{
// Breakout.
bLoop = false;
}
}
}
void CReadWriteLock::UnlockReader()
{
// Decrement number of readers.
DecrementReaderCount();
}
void CReadWriteLock::LockWriter()
{
// Enter critical section (prevent more than one writer).
EnterCriticalSection(&m_csLockWriter);
// Wait for current writer.
WaitForSingleObject(m_hWriterEvent, INFINITE);
// Set writer to non-signaled.
ResetEvent(m_hWriterEvent);
// Wait for current readers to finish.
WaitForSingleObject(m_hNoReadersEvent, INFINITE);
// Leave critical section.
LeaveCriticalSection(&m_csLockWriter);
}
void CReadWriteLock::UnlockWriter()
{
// Set writer event to signaled.
SetEvent(m_hWriterEvent);
}
void CReadWriteLock::IncrementReaderCount()
{
// Enter critical section.
EnterCriticalSection(&m_csReaderCount);
// Increase reader count.
m_nReaderCount++;
// Reset the no readers event.
ResetEvent(m_hNoReadersEvent);
// Leave critical section.
LeaveCriticalSection(&m_csReaderCount);
}
void CReadWriteLock::DecrementReaderCount()
{
// Enter critical section.
EnterCriticalSection(&m_csReaderCount);
// Decrease reader count.
m_nReaderCount--;
// Are all readers out?
if(m_nReaderCount <= 0)
{
// Set the no readers event.
SetEvent(m_hNoReadersEvent);
}
// Leave critical section.
LeaveCriticalSection(&m_csReaderCount);
}
历史
- 2006-11-01:版本 1.0 - 首次发布。
- 2006-11-20:版本 1.1 - 通过实现私有构造函数和赋值运算符来防止浅拷贝。
- 2006-11-21:版本 1.2 -
LockWriter()
中等待无读者的while
循环被WaitForSingleObject()
替换。