我一直在研究WinAPI中可用的所有不同的同步原语,但一直在努力应该是简单的东西。为什么以下代码不起作用?
class MultiThreadedCounter
{
private:
int count; HANDLE hMutex;
public:
void IncrementCounter()
{
if (count == 0)
hMutex = CreateMutex(NULL, TRUE, NULL);
count++;
}
void DecrementCounter()
{
count--;
if (count == 0)
ReleaseMutex(hMutex);
}
void WaitForCounterToReachZero()
{
WaitForSingleObject(hMutex, INFINITE);
CloseHandle(hMutex);
}
};
MultiThreadedCounter extractionsInProgressCounter;
肯定会以正确的顺序进行调用。首先,在异步任务(这里是线程休眠)之前,主线程调用IncrementCounter()
。然后主线程调用WaitForCounterToReachZero()
。最后,后台线程在完成其工作时调用DecrementCounter()
,这应该允许主线程继续。
然而,WaitForSingleObject
并未等待。它会立即返回WAIT_OBJECT_0
。它为什么这样做?这几乎就像互联网从未被最初获得过。但是,在调用CreateMutex
时,我将bInitialOwner
设置为TRUE
,这就是为什么我不明白为什么它似乎没有获得。我想我误解了一些事情。
谢谢。
编辑1:
好的,为了测试,我将IncrementCounter()
更改为:
void IncrementCounter()
{
if (count == 0)
{
hMutex = CreateMutex(NULL, TRUE, NULL);
DWORD var1 = WaitForSingleObject(hMutex, INFINITE);
DWORD var2 = WaitForSingleObject(hMutex, INFINITE);
}
count++;
}
真的,真的应该已经死了,但是不,两个对WaitForSingleObject
的调用立即返回,var1
和var2
都等于0(根据标题是WAIT_OBJECT_0)
对CreateMutex
的调用无法正常工作,是吗?然而,hMutex
被设置为合理的值,而GetLastError()
仍为0。所以很困惑......
编辑2:谢谢大家的帮助。我从来没有让这个工作,但是,我现在意识到我无论如何都是这样做的。所以我将所有内容都切换到一个事件,此时它起作用,然后添加了一些条件来处理乱序增量&递减,然后是保护计数变量的关键部分。它有效:)
class MultiThreadedCounter
{
private:
int count; HANDLE hEvent; CRITICAL_SECTION criticalSection;
public:
void IncrementCounter()
{
EnterCriticalSection(&criticalSection);
if (count == 0)
ResetEvent(hEvent);
count++;
LeaveCriticalSection(&criticalSection);
}
void DecrementCounter()
{
EnterCriticalSection(&criticalSection);
if (count > 0)
count--;
if (count == 0)
SetEvent(hEvent);
LeaveCriticalSection(&criticalSection);
}
void WaitForCounterToReachZero()
{
WaitForSingleObject(hEvent, INFINITE);
}
MultiThreadedCounter()
{
hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
InitializeCriticalSection(&criticalSection);
count = 0;
}
~MultiThreadedCounter()
{
CloseHandle(hEvent);
DeleteCriticalSection(&criticalSection);
}
};
答案 0 :(得分:2)
您没有显示MultiThreadedCounter
的构造函数。如果没有这个,就没有地方可以将count
初始化为0,这意味着第一次调用IncrementCounter
几乎肯定不会调用CreateMutex
您的构造函数应该类似于
MultiThreadedCounter()
: count(0)
, hMutex(NULL)
{
}
顺便说一句,如果您需要在单个进程中在线程之间使用锁,则可以考虑使用critical section代替。