线程基础(二)
来源:互联网 发布: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;}
- 线程基础(二)
- (二)线程同步基础
- java线程---基础(二)
- Java学习:线程基础(二)
- 线程同步基础(二十)
- 线程池基础详解(二)
- java基础---线程二
- 1.2线程基础(二)
- 线程同步基础(二)
- 线程基础----如何编写java线程池(二)
- C#中的线程(二)线程同步基础
- Java线程基础(二):Synchronization
- Java基础之多线程二
- Java基础之多线程(二)
- 线程基础二--卖票问题
- C#中的线程(二) 线程同步基础
- C#中的线程(二) 线程同步基础
- C#中的线程(二) 线程同步基础
- jquery常用方法
- 开源的路由协议
- 数组 循环语句练习
- 什么是Javascript正则表达式
- DOTNET零碎要点---1.vb.net利用Oracle.DataAccess.dll链接Oracle数据库
- 线程基础(二)
- BSS段、数据段、代码段、堆与栈
- 将jar文件按的源码导入
- 请别小看杀毒性能———解放军演习 杀毒软件误杀武器系统致阵地摧毁
- 阿里云OS和Android的关系
- 线程基础(三)
- 一维数组和二维数组的转换表示(C#)
- 惠普架构文档模版学习笔记
- 关于JavaScript的push()函数