Проблема пробуждения нескольких потоков с помощью условной переменной 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-функций. Вы не знаете, почему это не работает, потому что вы никогда не проверяете ошибки.

Другие вопросы по тегам