简体   繁体   English

同步两个线程-WinAPI

[英]Synchronizing two threads - winapi

Program below is a synchronization between two threads using a Mutex. 下面的程序是使用Mutex在两个线程之间进行同步。

It compiles, works and prints what I want in order(alternating R/W for the 2 threads), but it crashes after it's done. 它可以按顺序编译,工作和打印我想要的内容(两个线程交替使用R / W),但是在完成后会崩溃。 Any idea why? 知道为什么吗?

I think it has to do with closing TName handle, if I comment that part it doesn't crash, but I'd like to close opened handles. 我认为这与关闭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();
}

You should never cast a function pointer. 您永远不要强制转换函数指针。 Remove the (LPTHREAD_START_ROUTINE) casts from your code, fix the compiler errors, and try again. 从您的代码中删除(LPTHREAD_START_ROUTINE)强制转换,修复编译器错误,然后重试。 Never use casts to quell compiler errors. 切勿使用强制转换来平息编译器错误。

The lpStartAddress parameter of CreateThread is of type LPTHREAD_START_ROUTINE . CreateThreadlpStartAddress参数的类型为LPTHREAD_START_ROUTINE Which is a function pointer compatible with this signature: 与此签名兼容的函数指针:

DWORD WINAPI ThreadProc(LPVOID lpParameter);

So you need to supply what the function expects. 因此,您需要提供功能期望的内容。 Your function Reader does not fit the bill. 您的功能Reader器不符合要求。 Change its signature to be like this: 更改其签名,如下所示:

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

And likewise for Writer . 对于Writer也是如此。

Every time you cast something to suppress a compiler warning you are trading an easy to diagnose compile time error for a hard to diagnose run time error. 每次您投放某些内容以抑制编译器警告时,您都在将易于诊断的编译时错误换成难以诊断的运行时错误。 That's a very bad trade. 那是非常糟糕的交易。 So, as a general rule, don't use casts. 因此,一般而言,请勿使用强制转换。 Sometimes you'll need to break that rule, but do so in full understanding of what you are doing. 有时您需要违反该规则,但要完全了解自己的行为。

Your main function also has a somewhat bogus signature. 您的main功能还有一个虚假的签名。 If you don't want to process arguments, then you should declare it like this: 如果您不想处理参数,则应该这样声明:

int main()

Since you ignore the thread ID, you may as well pass NULL for the final parameter of CreateThread . 由于您忽略线程ID,因此最好将NULL传递给CreateThread的最终参数。

This also is wrong: 这也是错误的:

CloseHandle(TName);

The parameter of CloseHandle is of type HANDLE . CloseHandle的参数类型为HANDLE You are passing a pointer to an array. 您正在传递指向数组的指针。 You need to do this: 您需要这样做:

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

The Writer function does not return a value. Writer函数不返回值。 The compiler warns you about that, if you enable sufficient warnings. 如果启用足够的警告,编译器会警告您。 You should certainly do so. 您当然应该这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM