0

我有这个代码:

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

#include <time.h>

#define ITERATIONS 10

typedef struct NUMERE
{
    DWORD a;
    DWORD b;
} *PNUMERE;

HANDLE ghThreadHandle[2];
HANDLE ghEvents[2];
//HANDLE hEvent;

NUMERE nr;

DWORD WINAPI GenerateNumbers(PNUMERE nr)
{
    //PNUMERE nr = ((PNUMERE)param);
    if(nr == NULL)
        return -1;

    nr->a = rand() % 100;
    nr->b = (nr->a) * 2;

    _tprintf(TEXT("Generated\n"));

    //Sleep(10);

    return 0;
}

DWORD WINAPI DisplayNumbers(PNUMERE nr)
{
    //NUMERE nr = *((PNUMERE)param);

    _tprintf(TEXT("Displayed: %d %d\n"),nr->a,nr->b);

    return 0;
}

DWORD WINAPI DoStuff(PVOID param)
{
    int index = *((int*)param);

    for(unsigned int i = 0 ; i < ITERATIONS ; i++)
    {
        if(index == 0)
        {
            WaitForSingleObject(ghEvents[1],INFINITE);
            ResetEvent(ghEvents[0]);

            if(GenerateNumbers(&nr) == -1)
                _tprintf(TEXT("GenerateNumbers error!\n"));

            SetEvent(ghEvents[0]);
            ResetEvent(ghEvents[1]);
        }
        else
        {
            WaitForSingleObject(ghEvents[0],INFINITE);
            ResetEvent(ghEvents[1]);

            DisplayNumbers(&nr);

            SetEvent(ghEvents[1]);
            ResetEvent(ghEvents[0]);
        }
    }

    return 0;
}

DWORD GenerateThreads()
{
    int temp0 = 0, temp1 = 1;
    ghThreadHandle[0] = CreateThread(NULL
        ,0
        ,(LPTHREAD_START_ROUTINE)DoStuff
        ,(LPVOID)&temp0
        ,0
        ,NULL);

    if(NULL == ghThreadHandle[0])
        return -1;

    ghThreadHandle[1] = CreateThread(NULL
        ,0
        ,(LPTHREAD_START_ROUTINE)DoStuff
        ,(LPVOID)&temp1
        ,0
        ,NULL);

    if(NULL == ghThreadHandle[1])
    {
        CloseHandle(ghThreadHandle[0]);
        return -1;
    }

    return 0;
}

int main()
{   
    srand(time(NULL));

    ghEvents[0] = CreateEvent(NULL,TRUE,TRUE,TEXT("MyEvent0"));
    ghEvents[1] = CreateEvent(NULL,TRUE,TRUE,TEXT("MyEvent1"));

    if(NULL == ghEvents[0] || NULL == ghEvents[1])
    {
        _tprintf("Error creating events\n");
        return -1;
    }

    if(GenerateThreads() == -1)
    {
        _tprintf("Error GenerateThreads\n");
        return -1;
    }

    WaitForMultipleObjects(2,ghThreadHandle,TRUE,INFINITE);

    //getchar();

    CloseHandle(ghThreadHandle[0]);
    CloseHandle(ghThreadHandle[1]);

    CloseHandle(ghEvents[0]);
    CloseHandle(ghEvents[1]);

    return 0;
}

我希望交替调用这两个函数 (GenerateNumbers和)。DisplayNumbers但是,在启动时,GenerateNumbers它会被调用两次,然后它只是等待。该DisplayNumbers方法永远不会被调用。有人可以解释造成这种僵局的原因吗?

4

1 回答 1

3

GenerateThreads函数将局部变量的地址传递给另一个线程(temp0temp1)。然后该函数在启动线程后立即返回。这意味着其他线程现在正在访问已释放的内存。看来,当线程读取它们的param时,内存值变为零,因此两个线程都认为它们是GenerateNumbers线程。

添加额外的调试打印语句会更快地发现这个问题。

请注意,您在每个块的末尾仍然有一个竞争条件,因为您在重置唤醒事件之前通知另一个线程开始。另一个线程可能会醒来,完成它的工作,然后设置唤醒事件,这一切都在第一个线程从SetEvent. 然后第一个线程重置它的事件并等待它,导致它丢失唤醒事件并因此挂起。

于 2013-04-01T22:37:14.993 回答