Проблема пробуждения нескольких потоков с помощью условной переменной API в win32
У меня есть проблема в понимании, как работают переменные условия winapi.
С другой стороны, я хочу пару потоков, ожидающих каких-то условий. Затем я хочу использовать вызов 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().
Я не совсем уверен, что я сделал не так, но я бы предположил, что-нибудь проблема синхронизации?
Любая помощь будет оценена. (извините, если я повторно опубликовал более старую тему с другим украшением:)
1 ответ
Вы слишком поздно инициализируете переменные cond_rwlock и start_condition. Переместите код вверх, прежде чем запускать потоки. Поток может начать работать сразу, особенно на многоядерном компьютере.
И проверить возвращаемые значения API-функций. Вы не знаете, почему это не работает, потому что вы никогда не проверяете ошибки.