SleepConditionVariableCS将挂起

时间:2014-12-20 02:30:40

标签: c++ multithreading winapi synchronization condition-variable

我修改了" Using Condition Variables" MSDN中的示例。我创建了几个线程,它们分别有自己的生产者/消费者。 但是当附加到调试器时,程序通常会挂起。它始终挂在SleepConditionVariableCS。当我打破所有并继续调试时,程序将继续运行。我发现WakeAllConditionVariable没有唤醒一些线程调用SleepConditionVariableCS,对于Px在PExecutingTask-> BufferNotFull或PExecutingTask-> BufferNotEmpty已经是0x00000000(我认为这意味着条件变量被唤醒)。 如果没有附加到调试器,程序将不会挂起。

以前有人遇到过这个问题吗?怎么解决?

以下是代码:

#include <windows.h>

#include <stdlib.h>
#include <stdio.h>

#define BUFFER_SIZE 100

DWORD WINAPI ProducerThreadProc (PVOID p);
DWORD WINAPI ConsumerThreadProc (PVOID p);
class ExecutingTask
{
public:
    void Initialize()
    {
        InitializeConditionVariable (&BufferNotEmpty);
        InitializeConditionVariable (&BufferNotFull);

        InitializeCriticalSection (&BufferLock);

        QueueSize = 0;
        StopRequested = FALSE;

        hProducer = CreateThread(NULL, 0, ProducerThreadProc, (PVOID)this, 0, NULL);
        for (int i = 0; i < 20; i++)
        {
            PhConsumers[i] = CreateThread (NULL, 0, ConsumerThreadProc, (PVOID)this, 0, NULL);
        }
    }

    void Stop()
    {
        EnterCriticalSection (&BufferLock);
        StopRequested = TRUE;
        LeaveCriticalSection (&BufferLock);

        WakeAllConditionVariable (&BufferNotFull);
        WakeAllConditionVariable (&BufferNotEmpty);

        WaitForSingleObject(hProducer, INFINITE);
        WaitForMultipleObjects(20, (HANDLE *)&PhConsumers, true, INFINITE);
        CloseHandle(hProducer);
        for (unsigned int i = 0; i < 20; i++)
        {
            CloseHandle(PhConsumers[i]);
        }
    }

public:
    ULONG QueueSize;

    CONDITION_VARIABLE BufferNotEmpty;
    CONDITION_VARIABLE BufferNotFull;
    CRITICAL_SECTION   BufferLock;

    BOOL StopRequested;

    HANDLE PhConsumers[20];
    HANDLE hProducer;
};

DWORD WINAPI ProducerThreadProc (PVOID p)
{
    ExecutingTask* PExecutingTask = (ExecutingTask*)p;

    while (true)
    {
        EnterCriticalSection (&PExecutingTask->BufferLock);

        while (PExecutingTask->QueueSize >= BUFFER_SIZE && PExecutingTask->StopRequested == FALSE)
        {
            // Buffer is full - sleep so consumers can get items.
            SleepConditionVariableCS (&PExecutingTask->BufferNotFull, &PExecutingTask->BufferLock, INFINITE);
        }

        if (PExecutingTask->StopRequested == TRUE)
        {
            LeaveCriticalSection (&PExecutingTask->BufferLock);
            break;
        }

        // Produce an item.
        PExecutingTask->QueueSize++;
        LeaveCriticalSection (&PExecutingTask->BufferLock);
        WakeConditionVariable (&PExecutingTask->BufferNotEmpty);
    }

    return 0;
}

DWORD WINAPI ConsumerThreadProc (PVOID p)
{
    ExecutingTask* PExecutingTask = (ExecutingTask*)p;

    while (true)
    {
        EnterCriticalSection (&PExecutingTask->BufferLock);

        while (PExecutingTask->QueueSize == 0 && PExecutingTask->StopRequested == FALSE)
        {
            // Buffer is empty - sleep so producers can create items.
            SleepConditionVariableCS (&PExecutingTask->BufferNotEmpty, &PExecutingTask->BufferLock, INFINITE);
        }

        if (PExecutingTask->StopRequested == TRUE)
        {
            LeaveCriticalSection (&PExecutingTask->BufferLock);
            break;
        }

        // Consume an item.
        PExecutingTask->QueueSize--;
        LeaveCriticalSection (&PExecutingTask->BufferLock);
        WakeConditionVariable (&PExecutingTask->BufferNotFull);
    }
    return 0;
}

DWORD WINAPI ThreadProc (PVOID p)
{
    ExecutingTask task;
    task.Initialize();
    Sleep(1000);
    task.Stop();

    printf ("%u exit\n", &task);

    return 0;
};

int main ( void )
{
    HANDLE hTaskThreads[50];
    for (int i = 0; i < 50; i++)
    {
        hTaskThreads[i] = CreateThread (NULL, 0, ThreadProc, NULL, 0, NULL);
    }

    WaitForMultipleObjects(50, hTaskThreads, true, INFINITE);
    for (int i = 0; i < 50; i++)
    {
        CloseHandle(hTaskThreads[i]);
    }
}

0 个答案:

没有答案