线程基础(三)
来源:互联网 发布:s40软件下载 编辑:程序博客网 时间:2024/06/05 07:09
3、信号量
信号量,相当于一个计数器,用于限制可使用资源线程的数目。信号量允许多个线程在同一时刻访问共享资源,但是需要限制通一时刻访问此资源的最大线程数目。
CSemaphore类构造函数
CSemaphore(
LONG lInitialCount = 1,
LONG lMaxCount = 1,
LPCTSTR pstrName = NULL,
LPSECURITY_ATTRIBUTES lpsaAttributes = NULL
);
参数说明:
lInitialCount:信号量对象的初始计数值,即可访问线程数目的初始值,取值范围 0≤lInitialCount≤lMaxCount
lMaxCount:信号量对象的计数最大值,即同一时刻可访问资源的最大线程数目
pstrName:信号量的名字
lpsaAttributes :信号量的安全属性
用法:
CSemaphore*m_pSemaphore;声明一个信号量对象
m_pSemaphore= new CSemaphore(2,3);新建一个信号量对象
WaitForSingleObject(m_pSemaphore->m_hObject,INFINITE);等待信号量,如果为最大值,则一直等待
ReleaseSemaphore(m_pSemaphore->m_hObject,1,NULL);信号量减少1
示例:
#include "threadTest.h"#include <afxmt.h>#ifdef _DEBUG#define new DEBUG_NEW#endifCWinApp theApp;using namespace std;CSemaphore* m_pSemaphore;CCriticalSection cs;DWORD WINAPI myFunProc1(LPVOID lpParaneter);DWORD WINAPI myFunProc2(LPVOID lpParaneter);DWORD WINAPI myFunProc3(LPVOID lpParaneter);DWORD WINAPI myFunProc4(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{m_pSemaphore = new CSemaphore(2,3);HANDLE thread[4];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);thread[3] = CreateThread(NULL,0,myFunProc4,NULL,0,NULL);WaitForMultipleObjects(4,thread,TRUE,INFINITE);for (int i = 0;i<4;i++){CloseHandle(thread[i]);}return 0;}}else{_tprintf(_T("错䨪误¨®: GetModuleHandle 失º¡ì败㨹\n"));nRetCode = 1;}return nRetCode;}DWORD WINAPI myFunProc1(LPVOID lpParaneter){while (total){//等待信号量,如果为最大数目,则一直等待WaitForSingleObject(m_pSemaphore->m_hObject,INFINITE);cs.Lock();cout<<"线程1访问共享资源"<<endl;cs.Unlock();Sleep(200);//信号量计数减少1ReleaseSemaphore(m_pSemaphore->m_hObject,1,NULL);}return 0;}DWORD WINAPI myFunProc2(LPVOID lpParaneter){while (total){//等待信号量,如果为最大数目,则一直等待WaitForSingleObject(m_pSemaphore->m_hObject,INFINITE);cs.Lock();cout<<"线程2访问共享资源"<<endl;cs.Unlock();Sleep(200);//信号量计数减少1ReleaseSemaphore(m_pSemaphore->m_hObject,1,NULL);}return 0;}DWORD WINAPI myFunProc3(LPVOID lpParaneter){while (total){//等待信号量,如果为最大数目,则一直等待WaitForSingleObject(m_pSemaphore->m_hObject,INFINITE);cs.Lock();cout<<"线程3访问共享资源"<<endl;cs.Unlock();Sleep(200);//信号量计数减少1ReleaseSemaphore(m_pSemaphore->m_hObject,1,NULL);}return 0;}DWORD WINAPI myFunProc4(LPVOID lpParaneter){while (total){//等待信号量,如果为最大数目,则一直等待WaitForSingleObject(m_pSemaphore->m_hObject,INFINITE);cs.Lock();cout<<"线程4访问共享资源"<<endl;cs.Unlock();Sleep(200);//信号量计数减少1ReleaseSemaphore(m_pSemaphore->m_hObject,1,NULL);}return 0;}
4、互斥量(Mutex)
互斥量对象与临界区对象很相似,互斥对象和临界区都可以用于各个线程间。当然使用临界区会更节省系统资源,而且更有效率。但是互斥对象可以再进程间是用,而临界区对象只能在同一进程的各个线程之间是用。
CMutex定义:
CMutex(
BOOL bInitiallyOwn = FALSE,
LPCTSTR lpszName = NULL,
LPSECURITY_ATTRIBUTES lpsaAttribute = NULL
);
参数说明:
bInitiallyOwn:指定如果创建CMutex对象,是否最初获得资源控制
lpszName:互斥量名字ID
lpsaAttribute:通常设为NULL
使用方法:
CMutex m_Mutex(FALSE, “MutexName”);创建互斥对象
m_Mutex.Lock();加锁
m_Mutex.UnLock();解锁
示例:
#include "threadTest.h"#include <afxmt.h>#ifdef _DEBUG#define new DEBUG_NEW#endifCWinApptheApp; using namespace std;char szMutexText[] = "Mutex_1";CMutexm_Mutex(FALSE, szMutexText);CEventm_Event(FALSE, FALSE); DWORDWINAPI myFunProc1(LPVOID lpParaneter);inttotal = 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 { cout << "程序进入MAIN函数" << endl; m_Mutex.Lock(); cout << "程序进入互斥量" << endl; m_Event.ResetEvent(); HANDLE hThread = CreateThread(NULL,0, myFunProc1, NULL, 0, NULL); WaitForSingleObject(m_Event.m_hObject,INFINITE); m_Mutex.Unlock(); return0; } } else { _tprintf(_T("错误:GetModuleHandle 失败\n")); nRetCode = 1; } returnnRetCode;}DWORDWINAPI myFunProc1(LPVOID lpParaneter){ Sleep(5000); m_Event.SetEvent(); return 0UL;}
编译本程序可生成threadTest.exe文件,运行两个此可执行文件,可看到先开启的进程会打印出两行文字“程序进入MAIN函数”和“程序进入互斥量”,第二个只打出一行“程序进入MAIN函数”,等待5秒后第二个进程才打印出“程序进入互斥量”。这说明互斥对象可以在进程间使用。
- 线程基础(三)
- 线程基础----java对象锁(三)
- 多线程基础四(三)、暂停线程
- Linux多线程基础学习(三)线程生命周期
- Jmeter基础(三)--线程组、调度器
- Linux编程基础之多线程编程(三)
- 黑马程序员--JAVA基础复习之多线程(三)线程间通信 生产者消费者
- 【Java基础之线程同步(三)】使用ReentrantLock Condition实现线程同步
- Java线程基础(2)-实现线程的三种基本方法
- 多线程基础四(三)、yield方法、线程优先级以及守护线程
- [多线程之旅] 三、线程同步基础
- <4>Qualcomm Camera基础 三线程
- Java并发基础(三)-线程安全
- Java基础——Java重点基础之多线程(三) 注意
- Java线程基础(三):线程调度以及wait/notify
- Thread 线程(三)
- 线程学习(三)
- Java线程(三)
- 线程基础(二)
- BSS段、数据段、代码段、堆与栈
- 将jar文件按的源码导入
- 请别小看杀毒性能———解放军演习 杀毒软件误杀武器系统致阵地摧毁
- 阿里云OS和Android的关系
- 线程基础(三)
- 一维数组和二维数组的转换表示(C#)
- 惠普架构文档模版学习笔记
- 关于JavaScript的push()函数
- 面试题
- 计算器简单实现
- 为什么会受不了「指甲刮黑板的声音」?
- 5对象复制
- 好记性不如烂笔头