我一直在研究 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()(此处为线程 sleep )。然后主线程调用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 (根据 header ,它是 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);
}
};
最佳答案
您没有显示MultiThreadedCounter
的构造函数。如果没有这个,就没有地方将 count
初始化为 0,这意味着第一次调用 IncrementCounter
几乎肯定不会调用 CreateMutex
你的构造函数应该类似于
MultiThreadedCounter()
: count(0)
, hMutex(NULL)
{
}
顺便说一句,如果您需要在单个进程中的线程之间使用的锁,您可以考虑使用 critical section相反。
关于c++ - 为什么没有获取互斥体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18183288/