2013-08-12 49 views
2

我一直在研究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:

OK,所以测试,我改变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

我对winapi了解不多,但是在调用IncrementCounter之前调用WaitForSingleObject会发生什么? hMutex将处于什么状态,并且该功能是否能够应对? – PlasmaHH

+0

你能向我们展示你在哪些线程之间共享对象的代码吗?你确定吗,他们访问同一个对象而不是两个不同的对象? – ogni42

+0

@ ogni42:我会尽量在一分钟内将其编辑成问题,但是,我非常肯定他们肯定是同一个对象。 'MultiThreadedCounter extractionsInProgressCounter;'在任何函数之外,并且所有的函数都使用'extractionsInProgressCounter',它不会在任何地方重新定义。我几乎可以确定它是同一个对象,因为当调用WaitForSingleObject时,count被设置为1,hMutex被设置为最近运行的0xE8。所以初始化一定很合理。 – niemiro

回答

2

你没有表现一个构造MultiThreadedCounter。如果没有这个,没有地方来初始化count为0,这意味着将要IncrementCounter第一个电话几乎可以肯定不会叫CreateMutex

你的构造应该是这个样子

MultiThreadedCounter() 
    : count(0) 
    , hMutex(NULL) 
{ 
} 

顺便说一句,如果你需要在单个进程中的线程之间使用锁,您可以考虑使用critical section代替。

+0

这是一个好点 - 我只使用默认的构造函数。但是,我可以在'CreateMutex'行上放置一个断点,它肯定会被击中。另外,句柄被设置为一个合理的值,并且直到传递给'WaitForSingleObject'才会保持合理。我可以在那个时候使用'count == 1'的断点来确认,而且'DecrementCounter()'在那个时候也没有被调用。感谢您的帮助。 – niemiro

相关问题