[英]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.