C++11发布了四种不同的用于跨平台的锁,但其为了夸平台做了很多工作,在需要性能要求的情况下,大量的调用枷锁解锁必定会导致效率问题(现在计算机都这么快了这点运算其实又算得了什么呢,以后就不拿性能当幌子了),实际上在C++11发布之前就写好了一个夸平台的锁(大部分平台都可以用),代码比较简洁可以直接拿来用,自己平时用的比较多,真正原因就是自己不舍得这些代码用C++11的代替了。
这里要介绍的锁在同线程下支持递归枷锁,windows下使用临界区,不涉及内核对象,其他平台使用pthread库中的pthread_mutex_t对象,含有PTHREAD_MUTEX_RECURSIVE属性实现归枷锁,代码分了两个文件来实现,分别粘贴在下面,其中#include "PLTConfig.h"文件中定义了一些系统宏,参考QT定义的系统宏。
这是.h文件
/*
============================================================================================
Locker 快速锁对象
同线程内可以递归加锁
加锁和解锁必须在同一线程内
这种锁是进程内私有 不能和其他进程公用
windows下使用临界区 pthread下使用PTHREAD_MUTEX_RECURSIVE属性的互斥量
add 2013.11.22 by yuwf
Copyright (c), ...
=============================================================================================
*/
#ifndef _PALANTIR_LOCKER_H
#define _PALANTIR_LOCKER_H
#include "PLTConfig.h" // 根据系统定义 PLT_OS_WIN 和 PTHREAD 宏
#if defined(PLT_OS_WIN)
#include <windows.h>
#elif defined(PTHREAD)
#include <pthread.h>
#endif
namespace Palantir
{
// 允许加锁线程递归加锁
class Locker
{
public:
Locker();
~Locker();
// 加锁 不是同一线程枷锁会阻塞
void Lock();
// 非阻塞 枷锁成功返回true 否则返回false
bool TryLock();
// 解锁
void Unlock();
protected:
#if defined(PLT_OS_WIN)
CRITICAL_SECTION m_critical_section; // 临界区
#elif defined(PTHREAD)
pthread_mutex_t m_mutex; // 互斥锁
#endif
private:
// 禁止拷贝和赋值构造
Locker( const Locker& ) {};
Locker& operator = ( const Locker& ) { return *this; };
};
// 空锁 辅助使用
class EmptyLocker
{
public:
// 加锁
void Lock() {};
bool TryLock() { return true; };
// 解锁
void Unlock() {};
};
// 加锁辅助工具
template<class _LockerType_>
class LockerGuard
{
public:
LockerGuard( _LockerType_& locker )
: m_locker(locker)
{
locker.Lock();
}
~LockerGuard()
{
m_locker.Unlock();
}
protected:
_LockerType_& m_locker;
};
typedef LockerGuard<Locker> AutoLocker;
}
#endif
这是.cpp文件
/*
============================================================================================
Locker 快速锁对象 实现文件
add 2013.11.22 by yuwf
Copyright (c), ...
=============================================================================================
*/
#include "PLTLocker.h"
namespace Palantir
{
Locker::Locker()
{
#if defined(PLT_OS_WIN)
InitializeCriticalSection( &m_critical_section );
#elif defined(PTHREAD)
pthread_mutexattr_t attr;
pthread_mutexattr_init( &attr );
pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ); // 这个互斥锁可递归加锁 因为windows下的临界区可以递归加锁
pthread_mutex_init( &m_mutex, &attr );
#endif
}
Locker::~Locker()
{
#if defined(PLT_OS_WIN)
DeleteCriticalSection( &m_critical_section );
#elif defined(PTHREAD)
pthread_mutex_destroy( &m_mutex );
#endif
}
void Locker::Lock()
{
#if defined(PLT_OS_WIN)
EnterCriticalSection( &m_critical_section );
#elif defined(PTHREAD)
pthread_mutex_lock( &m_mutex );
#endif
}
bool Locker::TryLock()
{
#if defined(PLT_OS_WIN)
if ( !TryEnterCriticalSection( &m_critical_section ) )
{
return false;
}
#elif defined(PTHREAD)
if( pthread_mutex_trylock( &m_mutex ) != 0 )
{
return false;
}
#endif
return true;
}
void Locker::Unlock()
{
#if defined(PLT_OS_WIN)
LeaveCriticalSection( &m_critical_section );
#elif defined(PTHREAD)
pthread_mutex_unlock( &m_mutex );
#endif
}
}
代码中定义了一个空锁EmptyLocker,主要用来辅助使用,比如在后面要介绍的内存池中可以传入一个空锁来实现一个不需要枷锁的内存池,LockerGuard也是用来辅助使用,功能很简单,不做赘述。