线程基础(三)

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
#endif

CWinApp 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);
		//信号量计数减少1
		ReleaseSemaphore(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);
		//信号量计数减少1
		ReleaseSemaphore(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);
		//信号量计数减少1
		ReleaseSemaphore(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);
		//信号量计数减少1
		ReleaseSemaphore(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

#endif

CWinApptheApp;

 

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




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值