线程基础(二)

四、线程同步

实现线程同步主要有四种方法:事件、临界区、信号量、互斥量

1、事件(Event)

使用CEvent m_Event(FALSE,FALSE)创建一个初始为无信号,自动类型的事件。

m_Event.ResetEvent()设置事件为无信号。

m_Event.SetEvent()设置信号为有信号

WaitForSingleObject(m_Event.m_hObject,INFINITE)等待事件,直到事件有信号

示例:

#include "threadTest.h"
#include <afxmt.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CWinApp theApp;

using namespace std;
CEvent m_Event(FALSE,FALSE);
DWORD WINAPI myFunProc1(LPVOID lpParaneter);//声明线程函数
DWORD WINAPI myFunProc2(LPVOID lpParaneter); //声明线程函数
int i = 0,j = 0;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	HMODULE hModule = ::GetModuleHandle(NULL);

	if (hModule != NULL)
	{
				if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
		{
			_tprintf(_T("错误: MFC 初始化失败\n"));
			nRetCode = 1;
		}
		else
		{
			HANDLE thread[2];
			thread[0] = CreateThread(NULL,0,myFunProc1,NULL,0,NULL);//创建线程并立即执行
			thread[1] = CreateThread(NULL,0,myFunProc2,NULL,0,NULL); //创建线程并立即执行
			WaitForMultipleObjects(2,thread,TRUE,INFINITE);//等待所有线程结束为止
for (int i = 0;i<2;i++)
			{
				CloseHandle(thread[i]);
			}
			return 0;
		}
	}
	else
	{
		_tprintf(_T("错误: GetModuleHandle 失败\n"));
		nRetCode = 1;
	}

	return nRetCode;
}
DWORD WINAPI myFunProc1(LPVOID lpParaneter)
{
	while (true)
	{
		m_Event.ResetEvent();
		cout<<"爸爸向盘子里放了一个苹果,盘子里还有"<<++i<<"个苹果"<<endl;
		m_Event.SetEvent();
		Sleep(200);
	}
	return 0;
}
DWORD WINAPI myFunProc2(LPVOID lpParaneter)
{
	while (true)
	{
		WaitForSingleObject(m_Event.m_hObject,INFINITE);
		cout<<"儿子从盘子里拿了一个苹果,盘子里还有"<<--i<<"个苹果"<<endl;	
		Sleep(200);
	}
	return 0;
}

2、临界区(Critical Section)

即多个进程公用一个资源,同一时刻只能有一个进程访问。当一个进程抢占资源后便给资源加锁,此时其他进程不能抢占,当此进程使用完之后释放资源并解锁,这时其他进程可以竞争此资源。

使用CCriticalSection::Lock()给资源加锁,CCriticalSection::UnLock()解锁

示例:

#include "threadTest.h"
#include <afxmt.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CWinApp theApp;

using namespace std;
CCriticalSection cs;
DWORD WINAPI myFunProc1(LPVOID lpParaneter); //声明线程函数
DWORD WINAPI myFunProc2(LPVOID lpParaneter); //声明线程函数
DWORD WINAPI myFunProc3(LPVOID lpParaneter); //声明线程函数
int total = 100;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	HMODULE hModule = ::GetModuleHandle(NULL);

	if (hModule != NULL)
	{
		if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
		{
			_tprintf(_T("错误: MFC 初始化失败\n"));
			nRetCode = 1;
		}
		else
		{
			HANDLE thread[3];
			thread[0] = CreateThread(NULL,0,myFunProc1,NULL,0,NULL);//创建程并立即执行
			thread[1] = CreateThread(NULL,0,myFunProc2,NULL,0,NULL); //创建程并立即执行
			thread[2] = CreateThread(NULL,0,myFunProc3,NULL,0,NULL); //创建程并立即执行
			WaitForMultipleObjects(3,thread,TRUE,INFINITE);//等待所有线程¨¬结束为止
			for (int i = 0;i<3;i++)
			{
				CloseHandle(thread[i]);
			}
			return 0;
		}
	}
	else
	{
		_tprintf(_T("错误: GetModuleHandle 失败\n"));
		nRetCode = 1;
	}

	return nRetCode;
}
DWORD WINAPI myFunProc1(LPVOID lpParaneter)
{
	while (total)
	{
		cs.Lock();
		cout<<"售票员甲售出一张票,还剩"<<--total<<"张票"<<endl;
		cs.Unlock();
		Sleep(200);
	}
	return 0;
}
DWORD WINAPI myFunProc2(LPVOID lpParaneter)
{
	while (total)
	{
		cs.Lock();
		cout<<"售票员乙售出一张票,还剩"<<--total<<"张票"<<endl;
		cs.Unlock();
		Sleep(200);
	}
	return 0;
}
DWORD WINAPI myFunProc3(LPVOID lpParaneter)
{
	while (total)
	{
		cs.Lock();
		cout<<"售票员丙售出一张票,还剩"<<--total<<"张票"<<endl;
		cs.Unlock();
		Sleep(200);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值