gpt4 book ai didi

c++ - 通缉 : Elegant solution to race condition

转载 作者:太空狗 更新时间:2023-10-29 19:41:17 26 4
gpt4 key购买 nike

我有以下代码:

class TimeOutException
{};

template <typename T>
class MultiThreadedBuffer
{
public:
MultiThreadedBuffer()
{
InitializeCriticalSection(&m_csBuffer);
m_evtDataAvail = CreateEvent(NULL, TRUE, FALSE, NULL);
}
~MultiThreadedBuffer()
{
CloseHandle(m_evtDataAvail);
DeleteCriticalSection(&m_csBuffer);
}
void LockBuffer()
{
EnterCriticalSection(&m_csBuffer);
}
void UnlockBuffer()
{
LeaveCriticalSection(&m_csBuffer);
}
void Add(T val)
{
LockBuffer();
m_buffer.push_back(val);
SetEvent(m_evtDataAvail);
UnlockBuffer();
}
T Get(DWORD timeout)
{
T val;
if (WaitForSingleObject(m_evtDataAvail, timeout) == WAIT_OBJECT_0) {
LockBuffer();

if (!m_buffer.empty()) {
val = m_buffer.front();
m_buffer.pop_front();
}

if (m_buffer.empty()) {
ResetEvent(m_evtDataAvail);
}

UnlockBuffer();
} else {
throw TimeOutException();
}
return val;
}
bool IsDataAvail()
{
return (WaitForSingleObject(m_evtDataAvail, 0) == WAIT_OBJECT_0);
}
std::list<T> m_buffer;
CRITICAL_SECTION m_csBuffer;
HANDLE m_evtDataAvail;
};

单元测试表明,只要 T 的默认构造函数和复制/赋值运算符不抛出异常,此代码在单线程上使用时工作正常。因为我写的是 T,所以这是可以接受的。

我的问题是 Get 方法。如果没有可用数据(即未设置 m_evtDataAvail),则几个线程会阻塞 WaitForSingleObject 调用。当新数据可用时,它们都会进入 Lock() 调用。只有一个会通过并且可以取出数据并继续前进。在 Unlock() 之后,另一个线程可以继续前进,但会发现没有数据。目前它将返回默认对象。

我想要发生的是让第二个线程(和其他线程)返回到 WaitForSingleObject 调用。我可以添加一个解锁并执行 goto 的 else block ,但这感觉很糟糕。

该解决方案还增加了无限循环的可能性,因为每次返回都会重新开始超时。我可以添加一些代码来检查进入时的时钟并调整每次返回时的超时,但随后这个简单的 Get 方法开始变得非常复杂。

关于如何在保持可测试性和简单性的同时解决这些问题有什么想法吗?

哦,对于任何想知道的人来说,IsDataAvail 函数仅用于测试。它不会在生产代码中使用。添加和获取是将在非测试环境中使用的唯一方法。

最佳答案

您需要创建自动重置事件而不是手动重置事件。这保证了如果多个线程正在等待一个事件,并且当事件被设置时只有一个线程将被释放。所有其他线程将保持等待状态。您可以通过将 FALSE 传递给 CreateEvent 的第二个参数来创建自动重置事件应用程序接口(interface)。另外,请注意这段代码不是异常安全的,即在锁定缓冲区后,如果某些语句抛出异常,您的关键部分将不会被解锁。使用 RAII原则以确保即使在异常情况下也能解锁关键部分。

关于c++ - 通缉 : Elegant solution to race condition,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1406649/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com