簡體   English   中英

同步兩個線程-WinAPI

[英]Synchronizing two threads - winapi

下面的程序是使用Mutex在兩個線程之間進行同步。

它可以按順序編譯,工作和打印我想要的內容(兩個線程交替使用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();
}

您永遠不要強制轉換函數指針。 從您的代碼中刪除(LPTHREAD_START_ROUTINE)強制轉換,修復編譯器錯誤,然后重試。 切勿使用強制轉換來平息編譯器錯誤。

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函數不返回值。 如果啟用足夠的警告,編譯器會警告您。 您當然應該這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM