[英]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)強制轉換,修復編譯器錯誤,然后重試。 切勿使用強制轉換來平息編譯器錯誤。
CreateThread
的lpStartAddress
參數的類型為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.