简体   繁体   中英

Synchronizing two threads - winapi

Program below is a synchronization between two threads using a 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. 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.

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. Never use casts to quell compiler errors.

The lpStartAddress parameter of CreateThread is of type 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. Change its signature to be like this:

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

And likewise for 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. 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 .

This also is wrong:

CloseHandle(TName);

The parameter of CloseHandle is of type 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. The compiler warns you about that, if you enable sufficient warnings. You should certainly do so.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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