多线程同步的四种方式——事件对象

问题的引入:模仿12306多人同时抢票。

解决方法:使用事件对象。

事件对象

  事件对象也属于内核对象,包含一个使用计数,一个用于指明该事件是一个自动o重置的事件还是一个人工重置的事件的布尔值,另一个用于指明该事件处于已通知状态还是未通知状态的布尔值。

  有两种不同类型的事件对象。一种是人工重置的事件,另一种是自动重置的事件。当人工重置的事件得到通知时,等待该事件的所有线程均变成可调度线程。当一个自动重置的事件得到通知时,等待该事件的线程中只有一个线程变成可调度线程。

创建事件对象

HANDLE CreateEvent(
  LPSECURITY_ATTRIBUTES lpEventAttributes, //被忽略的,必须为NULL
  BOOL bManualReset, //TRUE表示手动重置状态,FALSE表示自动重置状态
  BOOL bInitialState, //TRUE表示初始是有信号状态,FALSE表示无信号
  LPTSTR lpName //事件对象的名称
); 

设置事件对象的信号状态

BOOL SetEvent(
  HANDLE hEvent 
); 

代码:

#include 	//需要调用windows Api
#include 
using namespace std;
DWORD WINAPI Fun1Proc(LPVOID lpParamter);
DWORD WINAPI Fun2Proc(LPVOID lpParamter);

HANDLE g_hEvent;
int nTickets = 100;	//总票数
int main()
{
	HANDLE hThred1, hThred2;
	hThred1 = CreateThread(NULL, 0, Fun1Proc,
		NULL, 0, NULL);
	hThred2 = CreateThread(NULL, 0, Fun2Proc,
		NULL, 0, NULL);
	CloseHandle(hThred1);
	CloseHandle(hThred2);

	g_hEvent = CreateEvent(
		NULL,	//被忽略的,必须为NULL
		FALSE,	//TRUE表示手动重置状态,FALSE表示自动重置状态
		FALSE,	//TRUE表示初始是有信号状态,FALSE表示无信号
		NULL);	//事件对象的名称

	SetEvent(g_hEvent);	//
	Sleep(4000);
	CloseHandle(g_hEvent);
	return 0;
}

DWORD WINAPI Fun1Proc(LPVOID lpParamter)
{
	while (TRUE)
	{
		WaitForSingleObject(g_hEvent, INFINITE);
		if (nTickets > 0)
		{
			Sleep(1);
			cout << "thread1 sell ticket:" << nTickets-- << endl;
		}
		else
		{
			break;
		}
		/*
			因为我们创建的是自动重置的事件对象,当线程1得到该事件对象后,
			系统会自动将该事件对象设置为非信号状态。如果不调用SetEvent,
			线程1、2后面都得不到该事件对象。
		*/
		SetEvent(g_hEvent);	//设置为有信号状态
		
	}
	return 0;
}

DWORD WINAPI Fun2Proc(LPVOID lpParamter)
{
	while (TRUE)
	{
		WaitForSingleObject(g_hEvent, INFINITE);
		if (nTickets > 0)
		{
			Sleep(1);
			cout << "thread2 sell ticket:" << nTickets-- << endl;
		}
		else
		{
			break;
		}
		SetEvent(g_hEvent);	//设置为有信号状态
	}
	return 0;
}

 

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