同步两个线程 - winapi

时间:2014-03-29 16:51:51

标签: c++ multithreading winapi synchronization

以下程序是使用互斥锁的两个线程之间的同步。

它按顺序编译,工作和打印我想要的东西(2个线程的交替R / W),但是在完成后它会崩溃。知道为什么吗?

我认为它与关闭TName句柄有关,如果我评论该部分它没有崩溃,但我想关闭打开的句柄。

HANDLE hMutex, hWriteDone, hReadDone;

int num, state;

void Writer()
{
    for(int x=10; x>=0; x--)
    {

        while (true)
        {

            if (WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED)
            {

                std::cout<<"In writing loop, no mutex!\n";

                ExitThread(0);
            }

            if (state == 0)
            {

                ReleaseMutex(hMutex);

                WaitForSingleObject(hReadDone, INFINITE);

                continue;
            }
            break;
        }
        std::cout<<"Write done\n";

        num= x;

        state= 0;

        ReleaseMutex(hMutex);

        PulseEvent(hWriteDone);
    }
}

void Reader()
{
    while(true)
    {

        if (WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED)
        {
            std::cout<<"In reader, no mutex!\n";

            ExitThread(0);

        }
        if (state == 1)
        {
            ReleaseMutex(hMutex);

            WaitForSingleObject(hWriteDone, INFINITE);

            continue;
        }

        if (num == 0)
        {

            std::cout<<"End of data\n";

            ReleaseMutex(hMutex);

            ExitThread(0);
        }
        else {

            std::cout<<"Read done\n";

            state=1;

            ReleaseMutex(hMutex);

            PulseEvent(hReadDone);

        }
    }
}

void main()
{

    HANDLE TName[2];
    DWORD ThreadID;

    state= 1;

    hMutex= CreateMutex(NULL, FALSE, NULL);
    hWriteDone= CreateEvent(NULL, TRUE, FALSE, NULL);
    hReadDone= CreateEvent(NULL, TRUE, FALSE, NULL);

    TName[0]= CreateThread(NULL, 0,
        (LPTHREAD_START_ROUTINE)Writer,
        NULL, 0, &ThreadID);

    TName[1]= CreateThread(NULL, 0,
        (LPTHREAD_START_ROUTINE)Reader,
        NULL, 0, &ThreadID);

    WaitForMultipleObjects(2, TName, TRUE, INFINITE);
    CloseHandle(TName);

    getchar();
}

2 个答案:

答案 0 :(得分:2)

你永远不应该转换函数指针。从代码中删除(LPTHREAD_START_ROUTINE)强制转换,修复编译器错误,然后重试。切勿使用强制转换来平息编译器错误。

答案 1 :(得分:1)

CreateThreadlpStartAddress参数属于LPTHREAD_START_ROUTINE类型。哪个是与此签名兼容的函数指针:

DWORD WINAPI ThreadProc(LPVOID lpParameter);

所以你需要提供函数所期望的东西。您的函数Reader不适合该帐单。将其签名更改为:

DWORD WINAPI Reader(LPVOID lpParameter)
{
    ....
}

同样适用于Writer

每次你施加某些东西来抑制编译器警告时,你都会很容易诊断编译时错误,因为很难诊断运行时错误。这是一个非常糟糕的交易。因此,作为一般规则,不要使用演员表。有时你需要打破这个规则,但要完全理解你在做什么。

您的main功能也有一些虚假的签名。如果你不想处理参数,那么你应该这样声明:

int main()

由于您忽略了线程ID,因此您也可以将NULL传递给CreateThread的最终参数。

这也是错误的:

CloseHandle(TName);

CloseHandle的参数属于HANDLE类型。您正在传递指向数组的指针。你需要这样做:

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

Writer函数不返回值。如果启用了足够的警告,编译器会向您发出警告。你当然应该这样做。