多线程火车票售票系统——人工重置事件对象实现线程同步(会有问题的)

本文通过一个售票系统的例子,介绍了Windows环境下如何利用事件对象实现线程间的同步操作。详细解析了CreateEvent函数的参数及其意义,并展示了人工重置事件对象在多线程环境中可能引发的问题。

#include <windows.h>
#include <iostream.h>

DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

int index = 0;
int tickets = 100;
HANDLE g_hEvent; //全局事件对象句柄

void main()
{
HANDLE hThread1;

 HANDLE hThread2;

hThread1 = CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2 = CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);

CloseHandle(hThread1);
CloseHandle(hThread2);

g_hEvent = CreateEvent(NULL,true,false,NULL); //创建事件对象,第二个参数为true,表示人工重置的。第三个参数false,表示事件对象初始值为无信号。第四个参数NULL,表示匿名的。
    SetEvent(g_hEvent); //设置为有信号状态
Sleep(4000); //让主线程放弃执行,不退出。进入等待状态,不占用CPU。

return;
}

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while (TRUE)
{
WaitForSingleObject(g_hEvent,INFINITE);//请求事件对象。如果为0,则不会死等,不管有没有信号,都会执行后面的代码。
ResetEvent(g_hEvent);
if (tickets > 0)
{
Sleep(1);
cout<<"thread1 sell tickets:"<<tickets--<<endl;
SetEvent(g_hEvent);
}
   else
{
SetEvent(g_hEvent);
break;
}   

}
return 0;
}

DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while (TRUE)
{
   WaitForSingleObject(g_hEvent,INFINITE);//请求事件对象。
ResetEvent(g_hEvent);
if (tickets > 0)
{
Sleep(1);
cout<<"thread2 sell tickets:"<<tickets--<<endl;
SetEvent(g_hEvent);
}
   else
{
SetEvent(g_hEvent);
break;
}    
}
return 0;
}

1、事件对象也是内核对象。包括一个使用计数、自动重置还是人工重置、状态。当人工重置事件对象获得通知时,等待该事件的所有线程均变为有信号状态。当自动重置的事件对象得到通知时,只有一个线程可以变为有信号状态。

2、CreateEvent:第一个参数一般为空。第二个参数,True,为人工重置,当线程获得信号后,要用ResetEvent设置成无信号。false,为自动,线程获得信号后,会自动设置为无信号状态。第三个参数,true,初始为有信号,false,初始为无信号。第四个参数,事件对象名字。

3、人工重置的对象,会出现多个线程同时运行的情况,不能起到保护的全局变量的作用。

4、问题:当  WaitForSingleObject(g_hEvent,INFINITE);//请求事件对象后,时间片玩,去执行第二个线程时,第二个线程仍然可以请求到事件对象的。

 5、当在多CPU平台下,两个线程可以同时运行的。可以同时获得事件对象的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值