线程基础(二)

来源:互联网 发布:s40软件下载 编辑:程序博客网 时间:2024/05/23 16:35

四、线程同步

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

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#endifCWinApp 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#endifCWinApp 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;}