2010-10-29 49 views
0

我在理解winapi條件變量如何工作時遇到問題。在win32中使用條件變量API喚醒多個線程的問題

在更具體的一面,我想要的是一些等待一些條件的線程。然後,我想使用WakeAllConditionVariable()調用來喚醒所有線程,以便它們可以工作。除了我只想讓線程開始的事實之外,他們沒有任何其他先決條件可以開始工作(就像在n生產者/ n用戶場景中那樣)。

這裏是到目前爲止的代碼:

#define MAX_THREADS 4 

CONDITION_VARIABLE start_condition; 
SRWLOCK   cond_rwlock; 
bool     wake_all; 

__int64 start_times[MAX_THREADS]; 

主線程:

int main() 
{ 
    HANDLE h_threads[ MAX_THREADS ]; 

    int tc; 
    for (tc = 0; tc < MAX_THREADS; tc++) 
    { 
     DWORD tid; 
     h_threads[tc] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)thread_routine,(void*)tc,0,&tid); 
     if(h_threads[tc] == NULL) 
     { 
      cout << "Error while creating thread with index " << tc << endl; 
      continue; 
     } 
    } 

    InitializeSRWLock(&cond_rwlock); 
    InitializeConditionVariable(&start_condition); 

    AcquireSRWLockExclusive(&cond_rwlock); 
     // set the flag to true, then wake all threads 
    wake_all = true; 
    WakeAllConditionVariable(&start_condition); 

    ReleaseSRWLockExclusive(&cond_rwlock); 

    WaitForMultipleObjects(tc, h_threads, TRUE, INFINITE); 

    return 0; 
} 

這裏是線程程序的代碼:

DWORD thread_routine(PVOID p_param) 
{ 
    int t_index = (int)(p_param); 

    AcquireSRWLockShared(&cond_rwlock); 

     // main thread sets wake_all to true and calls WakeAllConditionVariable() 
     // so this thread should start doing the work (?) 
    while (!wake_all) 
     SleepConditionVariableSRW(&start_condition,&cond_rwlock, INFINITE,CONDITION_VARIABLE_LOCKMODE_SHARED); 

    QueryPerformanceCounter((LARGE_INTEGER*)&start_times[t_index]); 
     // do the actual thread related work here 

    return 0; 
} 

此代碼不會做什麼我希望它能做到。有時候只有一個線程完成工作,有時候只有兩個或三個線程完成工作,但從來沒有完成任何工作主函數永遠不會通過WaitForMultipleObjects()調用。

我不完全確定我做錯了什麼,但我會假設一些同步問題?

任何幫助,將不勝感激。 (對不起,如果我重新發布舊主題不同的更衣:)

+0

您的代碼中存在爭用條件。如果其中一個線程在主線程獲得獨佔鎖之前獲取共享鎖,主線程將掛起在AcquireRWLockExclusive中。 – 2011-08-28 12:15:13

回答

4

您初始化cond_rwlock和start_condition變量爲時已晚。將代碼向上移動,之前您啓動線程。線程可能會立即開始運行,特別是在多核機器上。

並測試api函數的返回值。你不知道爲什麼它不起作用,因爲你從不檢查失敗。

+0

謝謝,這是做的伎倆,這是顯而易見的,它應該有.. – redeye 2010-10-29 17:29:14

+0

我最初創建的線程與CREATE_SUSPENDED標誌,然後調用ResumeThread _after_初始化代碼。當我改變CreateThread調用來創建它們以便它們立即啓動時,我忘了移動到也移動條件init代碼。我的錯 :) – redeye 2010-10-29 17:31:39