C++中Event使用

转载自:http://www.cnblogs.com/yuanzfy/archive/2011/08/26/2154460.html

之前线程同步用互斥锁Mutex或用户模式的CriticalSection等来进行同步,而且使用效果一直很好,直到最近遇到新问题,朋友推荐用事件去处理。但是对事件了解比较少,所以摘了篇文章看,另外自己做了下试验(所以代码不是转的哦)。

概念:

事件是用来同步地位不相等的线程的,事件可以用来使一个线程完成一件事情,然后另外的线程完成剩下的事情。

事件的使用很灵活,自动事件的激发态是由人工来控制的(超级重要,尤其是在需要精确掌控是否处于有信号状态的时候),而Mutex在释放(releaseMetux)后就一直处于激发态,直到线程WaitForSingleObject。事件可以用来控制经典的读写模型和生产者和消费者模型。相应的方式为,生成者等待消费者的消费,再消费者消费完后通知生产者进行生产。

Mutex是排他的占有资源,一般用于地位相等的线程进行同步。每个线程都可以排他的访问一个资源或代码段,不存在哪个线程对资源访问存在优先次序。一个线程只能在Mutex处于激发态的时候访问被保护的资源或代码段,线程可以通过WaitForSingelObject来等待Mutex,在访问资源完成之后,ReleaseMutex释放Mutex,此时Mutex处于激发态。

注意:对句柄使用WaitForSIngleObject()之后的副作用(句柄状态的自动变化)

Mutex具有成功等待的副作用,在用WaitForSingleObject()等待到Mutex后,Mutex自动变为无信号状态,直到调用ReleaseMutex()使Mutex变为有信号状态为止;

自动事件也具有成功等待的副作用;

手动事件没有,必须调用ResetEvent()使手动事件变为未激发态;

进程和线程也没有成功等待的副作用。当线程或者进程函数返回时,线程内核对象变为激发态,但WaitForSingleObject并没有使线程或者进程的内核对象变为未激发态。

总之,事件一般用于控制线程的先后顺序,而Mutex一般用于排他的访问资源。

Event的使用:

首先创建事件:

HANDLE CreateEvent(

  LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全属性

  BOOL bManualReset, // 复位方式,1为手动复位,0为自动复位

  BOOL bInitialState, // 初始状态,0为不可用状态即无信号,1为可用状态即有信号

  LPCTSTR lpName // 对象名称

  );

SetEvent()设置事件为有信号;ResetEvent()设置事件为无信号。

WaitForSingleObject()来等待Event变为有信号:

DWORD WaitForSignalObject(HANDLE hObject, DWORD dwMilliseconds);

返回值有以下几种:

WAIT_OBJECT_0 :表示等待对象已经变为有信号状态,如果设置为自动复位,还会把此信号再次变为无信号状态。

WAIT_TIMEOUT   :表示等待超时

WAIT_FAILED      :表示等待对象句柄是一个无效句柄。

代码示例:

功能:用主线程来等待子线程的执行结束

HANDLE hEvent;
int num=1;

DWORD WINAPI _threadProc(LPVOID lpParam)
{
	for(int i=0; i<10000; i++)
	{
		for(int j=0; j<10000; j++)
			;
	}

	num=10;
	SetEvent(hEvent);
	return 0;
}

void main()
{
	//手动复位,初始时无信号
	hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);
	if(hEvent==NULL)
	{	
		printf("hEvent is null\n");
		return;
	}

	HANDLE hThread=CreateThread(NULL, 0, _threadProc, NULL, 0, NULL);

	DWORD dwRet=WaitForSingleObject(hEvent, INFINITE);
	if(dwRet==WAIT_ABANDONED)
		printf("WAIT_ABANDONED\n");
	else if(dwRet==WAIT_TIMEOUT)
		printf("WAIT_TIMEOUT\n");
	else if(dwRet==WAIT_OBJECT_0)
		printf("有信号状态\n");
	else if(dwRet==WAIT_FAILED)
		printf("WAIT_FAILED\n");

	printf("sub thread run out, num is %d\n", num);
}

你可能感兴趣的:(多线程,C++)