在多线程环境,对资源进行访问的时候,一般都需要加锁。这时候就涉及到加锁的性能问题:
lock.h
#ifndef _LOCK_H_
#define _LOCK_H_
#include <windows.h>
//锁接口类
class ILock
{
public:
virtual ~ILock() {}
virtual void Lock() const = 0;
virtual void Unlock() const = 0;
};
//互斥对象锁类
class CMutex : public ILock
{
public:
CMutex();
~CMutex();
virtual void Lock() const;
virtual void Unlock() const;
private:
HANDLE m_mutex;
};
//临界区锁类
class CriSection : public ILock
{
public:
CriSection();
~CriSection();
virtual void Lock() const;
virtual void Unlock() const;
private:
CRITICAL_SECTION m_critclSection;
};
//自动锁
class CAutoLock
{
public:
CAutoLock(const ILock&);
~CAutoLock();
private:
const ILock& m_lock;
};
#endif
lock.cpp
#include "StdAfx.h"
#include "Lock.h"
//创建一个匿名互斥对象
CMutex::CMutex()
{
m_mutex = ::CreateMutex(NULL, FALSE, NULL);
}
//销毁互斥对象,释放资源
CMutex::~CMutex()
{
::CloseHandle(m_mutex);
}
//确保拥有互斥对象的线程对被保护资源的独自访问
void CMutex::Lock() const
{
DWORD d = WaitForSingleObject(m_mutex, INFINITE);
}
//释放当前线程拥有的互斥对象,以使其它线程可以拥有互斥对象,对被保护资源进行访问
void CMutex::Unlock() const
{
::ReleaseMutex(m_mutex);
}
//////////////////////////////////////////////////////////////////////////
//初始化临界资源对象
CriSection::CriSection()
{
::InitializeCriticalSection(&m_critclSection);
}
//释放临界资源对象
CriSection::~CriSection()
{
::DeleteCriticalSection(&m_critclSection);
}
//进入临界区,加锁
void CriSection::Lock() const
{
::EnterCriticalSection((LPCRITICAL_SECTION)&m_critclSection);
}
//离开临界区,解锁
void CriSection::Unlock() const
{
::LeaveCriticalSection((LPCRITICAL_SECTION)&m_critclSection);
}
//////////////////////////////////////////////////////////////////////////
//自动加锁
CAutoLock::CAutoLock(const ILock& m) : m_lock(m)
{
m_lock.Lock();
}
//自动解锁
CAutoLock::~CAutoLock()
{
m_lock.Unlock();
}
测试代码:
#include "Lock.h"
#include <iostream>
#include <process.h>
#include <time.h>
using namespace std;
#define ENABLE_MUTEX
#define ENABLE_CRITICAL_SECTION
#if defined (ENABLE_MUTEX)
CMutex g_Lock;//创建一个互斥对象类型锁
#elif defined (ENABLE_CRITICAL_SECTION)
CriSection g_Lock;//创建一个临界区类型锁
#endif
void LockCompare(int &nNum)
{
CAutoLock lock1(g_Lock);
nNum++;
}
//线程函数
unsigned int __stdcall StartThread(void *pParam)
{
char *pMsg = (char *)pParam;
if (!pMsg)
{
return (unsigned int)1;
}
CAutoLock lock2(g_Lock);
cout << pMsg << endl;
clock_t tStart = clock();
int nNum = 0;
for (int i=0; i<100000; i++)
{
LockCompare(nNum);//对nNum反复加锁
}
clock_t tEnd = clock();
#if defined (ENABLE_MUTEX)
cout << "The lock type is mutex, time = " << (tEnd - tStart) << " ms." << endl;
#elif defined (ENABLE_CRITICAL_SECTION)
cout << "The lock type is critical section, time = "<<(tEnd - tStart) << " ms." <<endl;
#endif
return (unsigned int)0;
}
int main(int argc, char* argv[])
{
unsigned int uThreadId1, uThreadId2;
char *pszMsg1 = "1st print thread.";
char *pszMsg2 = "2nd print thread.";
//创建两个工作线程,分别打印不同的消息
HANDLE hThread1 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)pszMsg1, 0, &uThreadId1);
HANDLE hThread2 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)pszMsg2, 0, &uThreadId2);
//等待线程结束
DWORD dwRet = WaitForSingleObject(hThread1,INFINITE);
if ( dwRet == WAIT_TIMEOUT )
{
TerminateThread(hThread1, 0);
}
dwRet = WaitForSingleObject(hThread2,INFINITE);
if ( dwRet == WAIT_TIMEOUT )
{
TerminateThread(hThread2, 0);
}
//关闭线程句柄,释放资源
::CloseHandle(hThread1);
::CloseHandle(hThread2);
system("pause");
return 0;
}
将测试代码中的宏 #define ENABLE_MUTEX 注释掉,禁掉互斥锁,启用临界区锁。对比测试,可以看出关键段的效率比互斥量要高!
有以下几点需要注意:
1、关键段与互斥量,两者都因为有“线程所有权”,所以只能用于线程的互斥,不可以用于线程的同步。
2、在同一个进程的多线程同步锁,宜用关键段锁,它的效率比互斥量要高!