四、线程同步
实现线程同步主要有四种方法:事件、临界区、信号量、互斥量
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;
}