线程基础(三)

来源:互联网 发布: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秒后第二个进程才打印出“程序进入互斥量”。这说明互斥对象可以在进程间使用。




原创粉丝点击