2013-08-12 47 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

相關問題