進程、線程同步互斥學習 —— 事件

關於事件,先看MSDN介紹:

Event Objects

Anevent object is a synchronization object whose state can be explicitly set to signaled by use of theSetEvent function. 

即:Event與其他線程同步不同,Event可以通過函數來設置有無信號量。


初始化

A thread uses theCreateEvent or CreateEventEx function to create an event object. The creating thread specifies the initial state of the object and whether it is a manual-reset or auto-reset event object. The creating thread can also specify a name for the event object. Threads in other processes can open a handle to an existing event object by specifying its name in a call to theOpenEvent function.

HANDLE WINAPI CreateEvent(
  __in_opt  LPSECURITY_ATTRIBUTES lpEventAttributes,
  __in      BOOL bManualReset,
  __in      BOOL bInitialState,
  __in_opt  LPCTSTR lpName
);
HANDLE WINAPI CreateEventEx(
  __in_opt  LPSECURITY_ATTRIBUTES lpEventAttributes,
  __in_opt  LPCTSTR lpName,
  __in      DWORD dwFlags,
  __in      DWORD dwDesiredAccess
);
bManualReset :指定將事件對象創建成手動復原還是自動復原。如果是TRUE(wait functions恢復到無信號狀態),那麼必須用ResetEvent函數來手工將事件的狀態復原到無信號狀態如果設置爲FALSE,當一個等待線程被釋放以後,系統將會自動將事件狀態復原爲無信號狀態。

bInitialState :指定初始化時是否爲有信號狀態,TRUE則有,FALSE則無。


The event object is useful in sending a signal to a thread indicating that a particular event has occurred.

事件對象是有用的在一個線程發送信號來表明一個特定的事件發生。


設置事件

Sets the specified event object to the signaled state.

BOOL WINAPI SetEvent(
  __in  HANDLE hEvent
);
即:讓事件變爲有信號狀態。


復位事件

Sets the specified event object to the nonsignaled state.

BOOL WINAPI ResetEvent(
  __in  HANDLE hEvent
);
即:讓事件變爲無信號狀態。


通過對事件對象進行操作,我們可以判斷一個特定事件是否發生,進行同步操作等。


測試代碼:

Event.h

#pragma once
#include <windows.h>

class ILock
{
public:
	virtual void lock() = 0;
	virtual void unlock() = 0;
};

class _CEvent : public ILock
{
public:
	_CEvent();
	~_CEvent();
	virtual void lock();
	virtual void unlock();
private:
	HANDLE m_hEvent;
};

class CLock
{
public:
	CLock(ILock&);
	~CLock();
private:
	ILock& m_lock;
};
Event.cpp

#include "stdafx.h"
#include "Event.h"
#include <assert.h>

_CEvent::_CEvent()
{
	m_hEvent = ::CreateEvent(NULL, FALSE, TRUE, NULL);
	assert(m_hEvent);
}

_CEvent::~_CEvent()
{
	::CloseHandle(m_hEvent);
}

void _CEvent::lock()
{
	WaitForSingleObject(m_hEvent, INFINITE);
}

void _CEvent::unlock()
{
	SetEvent(m_hEvent);
}

CLock::CLock(ILock& locker) : m_lock(locker)
{
	m_lock.lock();
}

CLock::~CLock()
{
	m_lock.unlock();
}
test.cpp

// Event_test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <process.h>
#include "Event.h"
#define THREADCOUNT 10
_CEvent g_event;
int nFood = 0;

unsigned int WINAPI EatThread(void *pParam)
{
	int i = (int)pParam;
	int nHasEaten = 0;
	while (true)
	{
		CLock lock(g_event);
		if (nFood > 0)
		{
			Sleep(100);
			std::cout << "消費者" << i << "進行消費,已經吃掉(" << ++nHasEaten << "),當前剩餘食物" << --nFood << std::endl;
		}
		else
		{
			break;
		}
	}
	return 0;
}

unsigned int WINAPI ProductThread(void *pParam)
{
	int i = 0;
	while (i < 52)
	{
		std::cout << "生產者進行生產,當前剩餘食物" << ++nFood << std::endl;
		i++;
	}
	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hProductThread;
	HANDLE hEatThread[THREADCOUNT];

	hProductThread = (HANDLE)_beginthreadex(NULL, 0, &ProductThread, (void *)0, 0, 0);
	WaitForSingleObject(hProductThread, INFINITE);

	for (int i = 0; i < THREADCOUNT; i++)
	{
		hEatThread[i] = (HANDLE)_beginthreadex(NULL, 0, &EatThread, (void *)i, 0, 0);
	}
	WaitForMultipleObjects(THREADCOUNT, hEatThread, TRUE, INFINITE);

	::CloseHandle(hProductThread);
	for (int i = 0; i < THREADCOUNT; i++)
	{
		::CloseHandle(hEatThread[i]);
	}

	system("pause");
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章