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 <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手法封装相互排斥锁的更多相关文章
- UNIX网络编程卷1 server程序设计范式7 预先创建线程,以相互排斥锁上锁方式保护accept
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.预先创建一个线程池.并让每一个线程各自调用 accept 2.用相互排斥锁代替让每一个线 ...
- Linux 同步方法剖析--内核原子,自旋锁和相互排斥锁
在学习 Linux® 的过程中,您或许接触过并发(concurrency).临界段(critical section)和锁定,可是怎样在内核中使用这些概念呢?本文讨论了 2.6 版内核中可用的锁定机制 ...
- RAII手法封装互斥锁
RAII手法是 Resource Acquisition is Initialization 的缩写,意为“资源获取即初始化”,在使用智能指针时也使用,下面是针对互斥量时的实现, #include & ...
- Linux程序设计学习笔记----多线程编程线程同步机制之相互排斥量(锁)与读写锁
相互排斥锁通信机制 基本原理 相互排斥锁以排他方式防止共享数据被并发訪问,相互排斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个相互排斥锁逻辑上绑定之后,对该资源的訪问操作例如以下: ...
- Linux互斥和同步应用程序(一):posix线程和线程之间的相互排斥
[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流.请勿用于商业用途] 有了进程的概念,为何还要使用线程呢? 首先,回 ...
- Linux多线程同步之相互排斥量和条件变量
1. 什么是相互排斥量 相互排斥量从本质上说是一把锁,在訪问共享资源前对相互排斥量进行加锁,在訪问完毕后释放相互排斥量上的锁. 对相互排斥量进行加锁以后,不论什么其它试图再次对相互排斥量加锁的线程将会 ...
- Linux同步与相互排斥应用(零):基础概念
[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] 当操作系统进入多道批处理系统时 ...
- 你应该掌握的C++ RAII手法:Scopegaurd
C++作为一门Native Langueages,在C++98/03时代,资源管理是个大问题.而内存管理又是其中最大的问题.申请的堆内存需要手动分配和释放,为了确保内存正确释放,一般原则是" ...
- android NDK编程:使用posix多线程与mutex相互排斥同步
MainActivity.java 调用原生方法 posixThreads(int threads, int iterations) 启动线程 package com.apress.threads; ...
随机推荐
- UVA 1347 Tour 【双调旅行商/DP】
John Doe, a skilled pilot, enjoys traveling. While on vacation, he rents a small plane and starts vi ...
- PyCharm配置gitHub远程仓储
在一个团队里,编码不能是闭门造车,git学起来: 1. GIT的基本介绍.安装及使用教程- @廖雪峰 2. pycharm配置github远程仓储- @谢小小XH
- Python与数据库[0] -> 数据库概述
数据库概述 / Database Overview 1 关于SQL / About SQL 构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一 ...
- 数学【P2524】 Uim的情人节礼物·其之弐 (康托展开)
因为某人@ZAGER挖坑让我讲一下康托展开,所以发现了这个题,顺便说一下康托展开是个什么东西 题目概括 给定n与一个数列,要求求出给定数列在n的全排列中的排名(按照字典序从小到大排列) 康托展开 先放 ...
- 九. 常用类库、向量与哈希1.Java基础类库
Java 的类库是 Java 语言提供的已经实现的标准类的集合,是 Java 编程的 API(Application Program Interface),它可以帮助开发者方便.快捷地开发 Java ...
- 四. Java继承和多态8.Java final关键字:阻止继承和多态
在 Java 中,声明类.变量和方法时,可使用关键字 final 来修饰.final 所修饰的数据具有“终态”的特征,表示“最终的”意思.具体规定如下: final 修饰的类不能被继承. final ...
- java File和Byte[]数组 相互转换
public class Test { public static void main(String[] args){ String filePath = "E:\\softoon\\wor ...
- init_machine 在Kernel中被调用的过程
以tiny4412为例: arch/arm/mach-exynos/mach-tiny4412.c MACHINE_START(TINY4412, "TINY4412") /* M ...
- java内存缓存,节省内存
缓存的对象 这个问题就是我们上面提到的极端情况,在Java中,会对-128到127的Integer对象进行缓存,当创建新的Integer对象时,如果符合这个这个范围,并且已有存在的相同值的对象,则返回 ...
- 【IntellJ IDEA】idea的Terminal窗口中文乱码 解决方法
在操作git命令在windows上的idea中的terminal窗口时,总是出现中文乱码的问题 本开始以为是git乱码的问题,如果是GIt中文乱码,解决方案:https://www.cnblogs.c ...