RAII手法封装互斥锁

CriticalSectionWrapper是一个接口类

class CriticalSectionWrapper {
 public:
  // Factory method, constructor disabled
  static CriticalSectionWrapper* CreateCriticalSection();

  virtual ~CriticalSectionWrapper() {}

  // Tries to grab lock, beginning of a critical section. Will wait for the
  // lock to become available if the grab failed.
  virtual void Enter() = 0;

  // Returns a grabbed lock, end of critical section.
  virtual void Leave() = 0;
};


返回父类的静态指针,方便于其他模块直接调用,接口父类是为了多态性,因为这儿支持跨平台

CriticalSectionWrapper* CriticalSectionWrapper::CreateCriticalSection() {
#ifdef _WIN32
  return new CriticalSectionWindows();
#else
  return new CriticalSectionPosix();
#endif
}



// RAII extension of the critical section. Prevents Enter/Leave mismatches and
// provides more compact critical section syntax.
class CriticalSectionScoped 
{
public:
	explicit CriticalSectionScoped(CriticalSectionWrapper* critsec): ptr_crit_sec_(critsec) 
	{
    		ptr_crit_sec_->Enter();
  	}

  	~CriticalSectionScoped() 
	{
    		if (ptr_crit_sec_)
		{
      			Leave();
    		}
  	}

private:
  	void Leave() 
	{
    		ptr_crit_sec_->Leave();
    		ptr_crit_sec_ = NULL;
  	}

 	CriticalSectionWrapper* ptr_crit_sec_;
};


CriticalSectionPosix类继承CriticalSectionWrapper类,实现了所有的方法

class CriticalSectionPosix : public CriticalSectionWrapper 
{
public:
	CriticalSectionPosix();
  	virtual ~CriticalSectionPosix();
	
  	virtual void Enter() OVERRIDE;
  	virtual void Leave() OVERRIDE;

private:
  	pthread_mutex_t mutex_;
};


CriticalSectionPosix类的实现

CriticalSectionPosix::CriticalSectionPosix()
{
 	pthread_mutexattr_t attr;
  	(void) pthread_mutexattr_init(&attr);
  	(void) pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  	(void) pthread_mutex_init(&mutex_, &attr);
}

CriticalSectionPosix::~CriticalSectionPosix() 
{
 	(void) pthread_mutex_destroy(&mutex_);
}

void CriticalSectionPosix::Enter() 
{
  	(void) pthread_mutex_lock(&mutex_);
}

void CriticalSectionPosix::Leave() 
{
  	(void) pthread_mutex_unlock(&mutex_);
}

CriticalSectionWrapper* acm_crit_sect_ = CriticalSectionWrapper::CreateCriticalSection();


当对临界数据进行操作时,创建CriticalSectionScoped的对象,参数调用CriticalSectionWrapper的工厂方法

  {

  CriticalSectionScoped lock(acm_crit_sect_);

}

离开作用域后自动释放锁。不用再去解锁,避免了很多异常情况。这是一种RAII编程,Resource acquisition is initialization,直译为“资源获取就是初始化”

这儿锁的资源需要去释放,这由含有acm_crit_sect_成员的类的析构函数去释放。避免内存泄露


谈下几个接口:

线程和线程的同步对象(互斥量,读写锁,条件变量)都具有属性。在修改属性前都需要对该结构进行初始化。使用后要把该结构回收。我们用pthread_ mutexattr_init函数对pthread_mutexattr结构进行初始化,用pthread_mutexattr_destroy函数对该结构进行回收。

 

名称::

pthread_mutexattr_init/pthread_mutexattr_destroy

功能:

初始化/回收pthread_mutexattr_t结构

头文件:

#include

函数原形:

int pthread_mutexattrattr_init(pthread_mutexattr_t *attr);

int pthread_mutexattrattr_destroy( pthread_mutexattr_t *attr );

参数:

attr    pthread_mutexattr_t结构变量

返回值:

若成功返回0,若失败返回错误编号。

      

 

 

      






 pthread_mutexattr_init将属性对象的值初始化为缺省值。并分配属性对象占用的内存空间。

attr中pshared属性表示用这个属性对象创建的互斥锁的作用域,它的取值可以是PTHREAD_PROCESS_PRIVATE(缺省值,表示由这个属性对象创建的互斥锁只能在进程内使用)或PTHREAD_PROCESS_SHARED。

 

互斥量属性分为共享互斥量属性和类型互斥量属性。两种属性分别由不同的函数得到并由不同的函数进行修改。pthread_mutexattr_getpshared和pthread_mutexattr_setpshared函数可以获得和修改共享互斥量属性。pthread_mutexattr_gettype和pthread_mutexattr_settype函数可以获得和修改类型互斥量属性。下面我们分别介绍。

 

名称::

pthread_mutexattr_getpshared/pthread_mutexattr_setpshared

功能:

获得/修改共享互斥量属性

头文件:

#include

函数原形:

int pthread_mutexattrattr_ getpshared ( const pthread_attr_t *restrict attr,int*restrict pshared);

int pthread_mutexattrattr_ setpshared (  const pthread_attr_t *restrict attr,int pshared);

参数:

 

返回值:

若成功返回0,若失败返回错误编号。

 

 

 

 

 

 





共享互斥量属性用于规定互斥锁的作用域。互斥锁的域可以是进程内的也可以是进程间的。pthread_mutexattrattr_ getpshared可以返回属性对象的互斥锁作用域属性。可以是以下值:PTHREAD_PROCESS_SHARED,PTHREAD_PROCESS_PRIVATE。如果互斥锁属性对象的pshared属性被置PTHREAD_PROCESS_SHARED。那么由这个属性对象创建的互斥锁将被保存在共享内存中,可以被多个进程中的线程共享。如果pshared属性被置为PTHREAD_PROCESS_PRIVATE,那么只有和创建这个互斥锁的线程在同一个进程中的线程才能访问这个互斥锁。

 

名称::

pthread_mutexattr_gettype/pthread_mutexattr_settype

功能:

获得/修改类型互斥量属性

头文件:

#include

函数原形:

int pthread_mutexattrattr_ getpshared ( const pthread_attr_t *restrict attr,int*restrict pshared);

int pthread_mutexattrattr_ setpshared (  const pthread_attr_t *restrict attr,int pshared);

参数:

 

返回值:

若成功返回0,若失败返回错误编号。

 

 

 

 

 

 

 

 

 

 

 

pthread_mutexattr_gettype函数可以获得互斥锁类型属性。缺省的互斥锁类型属性是PTHREAD_MUTEX_DEFAULT。

合法的类型属性值有:

PTHREAD_MUTEX_NORMAL;

PTHREAD_MUTEX_ERRORCHECK;

PTHREAD_MUTEX_RECURSIVE

PTHREAD_MUTEX_DEFAULT。

类型说明:

PTHREAD_MUTEX_NORMAL

这种类型的互斥锁不会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会引起这个线程的死锁。如果试图解锁一个由别的线程锁定的互斥锁会引发不可预料的结果。如果一个线程试图解锁已经被解锁的互斥锁也会引发不可预料的结果。

 

PTHREAD_MUTEX_ERRORCHECK

这种类型的互斥锁会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会返回一个错误代码。如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个错误代码。

 

PTHREAD_MUTEX_RECURSIVE

如果一个线程对这种类型的互斥锁重复上锁,不会引起死锁,一个线程对这类互斥锁的多次重复上锁必须由这个线程来重复相同数量的解锁,这样才能解开这个互斥锁,别的线程才能得到这个互斥锁。如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个错误代码。这种类型的互斥锁只能是进程私有的(作用域属性为PTHREAD_PROCESS_PRIVATE)。

 

PTHREAD_MUTEX_DEFAULT

这种类型的互斥锁不会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会引起不可预料的结果。如果试图解锁一个由别的线程锁定的互斥锁会引发不可预料的结果。如果一个线程试图解锁已经被解锁的互斥锁也会引发不可预料的结果。POSIX标准规定,对于某一具体的实现,可以把这种类型的互斥锁定义为其他类型的互斥锁。


你可能感兴趣的:(RAII手法封装互斥锁)