1、事件对象3个成员:
1) 使用计数;
2)指定是自动重置事件对象还是人工重置对象;
3)指明是初始状态,是有信号状态,还是无线号状态;
2、事件对象类型:
1)人工重置事件对象;
2)自动重置事件对象;
3、人工重置事件对象和自动重置事件对象的区别:
当人工重置的事件对象得到通知时,等待该事件对象的所有线程均变为可调度线程;当自动重置的事件对象得到通知时,等待该事件的线程中只有一个线程变为可调度的线程,同时操作系统会将该事件对象设置为无信号状态,这样当对所保护的代码执行完成后,需要调用SetEvent()函数将该事件对象设置为有信号状态。而人工事件对象,在一个线程得到该事件对象之后,操作系统并不会将该事件对象设置为无信号状态,除非现实滴调用ResetEvent()函数将其设置为无信号状态。否则该对象会一直是有信号状态。
4、代码:
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
DWORD WINAPI Fun1Proc (
LPVOID lpParameter
);
DWORD WINAPI Fun2Proc(
LPVOID lpParameter
);
;
int index=0;
int tickets=100;
HANDLE hEvent;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
int a;
//第一个参数:指向LPSECURITY_ATTRIBUTES 结构体 的指针;
//第二个参数:指定是自动重置事件对象(TRUE)还是人工重置对象(false);
//第三个参数:指明是初始状态,是有信号状态(TRUE),还是无线号状态(false);
//第四个参数:指明事件对象的名称;
hEvent = CreateEvent(NULL,false,TRUE,NULL);//如果第三个参数为false,结果会怎样?请思考!
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
scanf("%d",&a);
CloseHandle(hEvent);
}
DWORD WINAPI Fun1Proc(
LPVOID lpParameter // thread data
)
{
while(TRUE)
{
WaitForSingleObject(hEvent,INFINITE);
if(tickets>0)
{
Sleep(1);
printf("thread1 sell ticket : %d \n",tickets--);
}
else
break;
SetEvent(hEvent);// 如果把这个参数注释掉,会怎样?
}
return 0;
}
DWORD WINAPI Fun2Proc(
LPVOID lpParameter // thread data
)
{
while(TRUE)
{
WaitForSingleObject(hEvent,INFINITE);
if(tickets>0)
{
Sleep(1);
printf("thread1 sell ticket : %d \n",tickets--);
}
else
break;
SetEvent(hEvent);
}
return 0;
}
/**********************************************************************************************************************************为了实现线程同步,尽量不要使用人工重置对象,应该很容易出错,比如,如果是单核,你要考虑执行到某条语句时,会出现时间片到了,跳去执行另外一个线程;如果是多核,几个线程又是同时执行的,又会出现复杂的情况的。如果是自动的事件对象,一个线程得到改事件对象,那么操作系统会把该事件对象设置为无信号,这样其他线程就无法得到这个事件对象了,但也要注意,你使用完后,你要记住把这个事件对象设为有信号,要不然其他线程是得不到这个事件对象的。
***********************************************************************************************************************************/