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 <pthread.h>

函数原形:

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 <pthread.h>

函数原形:

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 <pthread.h>

函数原形:

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手法封装相互排斥锁的更多相关文章

  1. UNIX网络编程卷1 server程序设计范式7 预先创建线程,以相互排斥锁上锁方式保护accept

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.预先创建一个线程池.并让每一个线程各自调用 accept 2.用相互排斥锁代替让每一个线 ...

  2. Linux 同步方法剖析--内核原子,自旋锁和相互排斥锁

    在学习 Linux® 的过程中,您或许接触过并发(concurrency).临界段(critical section)和锁定,可是怎样在内核中使用这些概念呢?本文讨论了 2.6 版内核中可用的锁定机制 ...

  3. RAII手法封装互斥锁

    RAII手法是 Resource Acquisition is Initialization 的缩写,意为“资源获取即初始化”,在使用智能指针时也使用,下面是针对互斥量时的实现, #include & ...

  4. Linux程序设计学习笔记----多线程编程线程同步机制之相互排斥量(锁)与读写锁

    相互排斥锁通信机制 基本原理 相互排斥锁以排他方式防止共享数据被并发訪问,相互排斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个相互排斥锁逻辑上绑定之后,对该资源的訪问操作例如以下: ...

  5. Linux互斥和同步应用程序(一):posix线程和线程之间的相互排斥

    [版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流.请勿用于商业用途] 有了进程的概念,为何还要使用线程呢? 首先,回 ...

  6. Linux多线程同步之相互排斥量和条件变量

    1. 什么是相互排斥量 相互排斥量从本质上说是一把锁,在訪问共享资源前对相互排斥量进行加锁,在訪问完毕后释放相互排斥量上的锁. 对相互排斥量进行加锁以后,不论什么其它试图再次对相互排斥量加锁的线程将会 ...

  7. Linux同步与相互排斥应用(零):基础概念

    [版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途]         当操作系统进入多道批处理系统时 ...

  8. 你应该掌握的C++ RAII手法:Scopegaurd

    C++作为一门Native Langueages,在C++98/03时代,资源管理是个大问题.而内存管理又是其中最大的问题.申请的堆内存需要手动分配和释放,为了确保内存正确释放,一般原则是" ...

  9. android NDK编程:使用posix多线程与mutex相互排斥同步

    MainActivity.java 调用原生方法 posixThreads(int threads, int iterations) 启动线程 package com.apress.threads; ...

随机推荐

  1. hdu 1301(最小生成树)

    Jungle Roads Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  2. NetStream配置

    http://support.huawei.com/enterprise/docinforeader!loadDocument1.action?contentId=DOC1000067951& ...

  3. 小白到web前端工程师需要学习哪些知识?

    随着web3.0时代,那么web前端开发技术人才越来越吃香,而且web前端领域划分越来越细,对技术的需求越来越高,想学习web前端的人也是越来越多.那么,如何学习web前端知识?从哪开始?转型成为we ...

  4. 陕西师范大学第七届程序设计竞赛网络同步赛D ZQ的睡前故事【约瑟夫环1-N数到第k个出队,输出出队顺序/ STL模拟】

    链接:https://www.nowcoder.com/acm/contest/121/D来源:牛客网 题目描述 ZQ是一个拥有n女朋友的万人迷,她的每一个女朋友每天晚上都会挨个给他打电话,要他讲了睡 ...

  5. 微服务实施Spring Boot/Spring Cloud中踩过的坑(转)

    http://tietang.wang/2016/09/08/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%AE%9E%E6%9 ...

  6. 【SVN】删除SVN上的历史资源路径和SVN上的历史用户信息

    1.删除svn上历史资源路径 window--show view--other--svn资源库 可以右键选择删除 . ----------------------------------------- ...

  7. python 时间 相关

    http://www.jb51.net/article/47957.htm 不管何时何地,只要我们编程时遇到了跟时间有关的问题,都要想到 datetime 和 time 标准库模块,今天我们就用它内部 ...

  8. 在ubuntu12.04中安装wine和source insight

    1.安装wine sudo apt-get install wine 2.安装source insight 将source insight安装的可运行文件拷贝到ubuntu中.我拷贝到了~/Deskt ...

  9. C++之纯虚函数

    1. 纯虚函数形式 class Parent { public: ; }; 代码中的func1就是纯虚函数,没有函数体,没有函数的具体实现,有virtual,在函数名后面带有“ = 0”形式: 2.对 ...

  10. 在使用springMVC时,我使用了@Service这样的注解,发现使用注解@Transactional声明的事务不起作用

    问题出现的场景: 在使用spring mvc时,我使用了@Service这样的注解, 发现使用注解@Transactional声明的事务不起作用. 我的配置如下: <mvc:annotation ...