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. centos6.6部署mysql mmm高可用架构

    一.环境简述 1.工作逻辑图 2.MySQL-MMM优缺点 优点:高可用性,扩展性好,出现故障自动切换,对于主主同步,在同一时间只提供一台数据库写操作,保证的数据的一致性. 缺点:Monitor节点是 ...

  2. array数据初始化

    #include <iostream> int main() { ]={}; std::cout<<array[]<<]; } 试了试上面的代码发现,数组在用{}赋 ...

  3. SQL 并发-转

    脏读.不可重复读  共享锁.悲观锁 和 事务五种隔离级别   一.脏读.不可重复读.幻读1.脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个 ...

  4. CF978E Bus Video System【数学/前缀和/思维】

    [链接]: CF [分析]: 设上车前人数 x ,中途最大人数为 x+max ,最小人数为 x+min (max≥0,min≤0) 可得不等式组 x+max≤w, x+min≥0 整数解个数为 max ...

  5. java数组集合

    一.ArrayList 1. ArrayList底层采用数组实现,当使用不带参数的构造方法生成ArrayList对象时,实际上会在底层生成一个长度为10的Object类型数组2. 如果增加的元素个数超 ...

  6. 新疆大学ACM-ICPC程序设计竞赛五月月赛(同步赛)- Red Rover

    链接:https://www.nowcoder.com/acm/contest/116/A来源:牛客网 输入描述: Input consists of a single line containing ...

  7. csu1811(树上启发式合并)

    csu1811 题意 给定一棵树,每个节点有颜色,每次仅删掉第 \(i\) 条边 \((a_i, b_i)\) ,得到两颗树,问两颗树节点的颜色集合的交集. 分析 转化一下,即所求答案为每次删掉 \( ...

  8. 洛谷——P1029 最大公约数和最小公倍数问题

    P1029 最大公约数和最小公倍数问题 题目描述 输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P,Q的个数 条件: 1 ...

  9. [BZOJ1194][HNOI2006][强连通分量Tarjan+dfs]潘多拉的盒子

    [BZOJ1194][HNOI2006]潘多拉的盒子 Input 第一行是一个正整数S,表示宝盒上咒语机的个数,(1≤S≤50).文件以下分为S块,每一块描述一个咒语机,按照咒语机0,咒语机1„„咒语 ...

  10. ScrollView起始位置不是最顶部的解决办法

    最近遇到了打开带有ScrollView的页面布局默认起始位置不是最顶部的情况,最后发现问题是因为ScrollView内部嵌套了gridview,只需要设置gridview获取焦点为false即可. g ...