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. Java进阶之路,技术要点

    宏观方面 一.JAVA.要想成为JAVA(高级)工程师肯定要学习JAVA.一般的程序员或许只需知道一些JAVA的语法结构就可以应付了.但要成为JAVA(高级)工程师,您要对JAVA做比较深入的研究.您 ...

  2. Android 横向列表GridView 实现横向滚动

    Android 横向列表实现,可左右滑动,如下图 1.主界面布局代码:activity_main.xml a.包裹HorizontalScrollView控件是GirdView横向滚动的基本条件b.G ...

  3. [loj#101] 最大流 网络流模板

    #101. 最大流 内存限制:512 MiB时间限制:5000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 这是一道模板题. 给定  ...

  4. window 10 64bit 安装nodejs v7.0.5 + npm v4.1.2 + Express 4.x及搭建web开发环境

    1.先安装nodejs.npm. 2.然后安装Express (4.0之后需要安装express-generator) npm install -g express npm install -g ex ...

  5. Codeforces Round #446 (Div. 2) A. Greed【模拟】

    A. Greed time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...

  6. ECNU 3462 最小 OR 路径 (贪心 + 并查集)

    题目链接  EOJ Monthly 2018.1 Problem F 先假设答案的每一位都是$1$,然后从高位开始,选出那些该位置上为$0$的所有边,并查集判断连通性. 如果$s$和$t$可以连通的话 ...

  7. Winform打砖块游戏制作step by step第7节---碰撞检测

    一 引子 为了让更多的编程初学者,轻松愉快地掌握面向对象的思考方法,对象继承和多态的妙用,故推出此系列随笔,还望大家多多支持. 预备知识,无GDI画图基础的童鞋请先阅读一篇文章让你彻底弄懂WinFor ...

  8. Delphi CRC算法crcexecute

    function crcexecute(pcstring : string) : string ; forward; var  gnkey  : integer;  gnsalt : integer; ...

  9. CGCS2000坐标系与其他坐标系间的差异和转换方法

    转自 CGCS2000坐标系与其他坐标系间的差异和转换方法 1954北京坐标系和1980西安坐标系是以天文大地网等经典测量技术为基础的局部坐标系.­ CGCS2000是以地球质量中心为原点的地心大地坐 ...

  10. Spark jdbc postgresql数据库连接和写入操作源代码解读

    概述:Spark postgresql jdbc 数据库连接和写入操作源代码解读.具体记录了SparkSQL对数据库的操作,通过java程序.在本地开发和执行.总体为,Spark建立数据库连接,读取数 ...