1.互斥锁简介

互斥锁主要用于互斥,互斥是一种竞争关系,用来保护临界资源一次只被一个线程访问。 
POSIX Pthread提供下面函数用来操作互斥锁。

int pthread_mutex_init(pthread_mutex_t  *mutex,  const  pthread_mutexattr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
//返回:
//pthread_mutex_init总是返回0
//其他mutex函数返回0表示成功,非0的错误码表示失败
#define CHECK(exp) \
if(!exp) \
{ \
fprintf(stderr, "File:%s, Line:%d Exp:[" #exp "] is true, abort.\n",__FILE__, __LINE__); abort();\
}

 由于pthread系列函数返回成功的时候都是0,因此,我们可以写一个宏作为一个轻量级的检查手段,来判断处理错误。

实际使用的时候只需:     CHECK(!pthread_mutex_lock(&mutex));

2.互斥锁的封装

需要考虑以下几个问题:

a.互斥锁的初始化与销毁。 
b.互斥锁的操作:加锁和释放锁。

另外,我们的自己封装的类不应该有赋值和拷贝构造的语义,这一点跟单例模式类似,我们可以使我们的类继承自boost库的noncopyable。

//MutexLock.h

#ifndef __MUTEXLOCK_H__
#define __MUTEXLOCK_H__
#include <iostream>
#include <cstdio>
#include <boost/noncopyable.hpp>
#include <pthread.h>
#include <assert.h> #define CHECK(exp) \
if(!exp) \
{ \
fprintf(stderr, "File:%s, Line:%d Exp:[" #exp "] is true, abort.\n",__FILE__, __LINE__); abort();\
} class MutexLock : public boost::noncopyable
{
friend class Condition;//条件变量友元声明
public:
MutexLock();
~MutexLock();
void lock();
void unlock();
bool isLocking() const
{
return isLocking_;
}
pthread_mutex_t *getMutexPtr()
{
return &mutex_;
}
private:
void restoreMutexStatus()
{
isLocking_=true;
}
pthread_mutex_t mutex_;//互斥锁
bool isLocking_;
};
#endif

  这里完成了MutexLock 类的声明,但是这里还需要一些补充,那就是使用RAII(资源获取即初始化)技术,对MutexLock初始化和析构进行处理:初始化的时候加锁,析构的时候解锁,这就需要我们重新定义一个class MutexLockGuardMutexLock进行操作

class MutexLockGuard:public boost::noncopyable
{
public:
MutexLockGuard(MutexLock &mutex):mutex_(mutex){ mutex_.lock();}//构造时加锁
~MutexLockGuard()//析构时解锁
{
mutex_.unlock();
}
private:
MutexLock &mutex_;//注意这里为什么是引用!!!!
};

下面就要具体实现几个函数了,主要是: 
pthread_mutex_init()pthread_mutex_destroy()pthread_mutex_lock()pthread_mutex_unlock()这四个函数的封装:

#include "MutexLock.h"
MutexLock::MutexLock():isLocking_(false)
{
CHECK(!pthread_mutex_init(&mutex_,NULL));
}
MutexLock::~MutexLock()
{
assert(!isLocking());
CHECK(!pthread_mutex_destroy(&mutex_));
}
void MutexLock::lock()
{
CHECK(!pthread_mutex_lock(&mutex_))//先加锁再修改状态,保证以下赋值操作的原子性。
isLocking_=true;
} void MutexLock::unlock()
{
isLocking_=false;//先修改状态在解锁,保证赋值操作的原子性。
CHECK(!pthread_mutex_unlock(&mutex_));
}

封装以后,我们使用:

MutexLockGurad lock(mutex);//就是  MutexLock对象被另一个对象管理
对临界区进行加锁,而只要我们控制好lock变量的生存期,就能控制临界区,例如:
int count=;
{
MutexLockGurad lock(mutex);
count++;
}//临界区
//...
//离开lock的作用域,lock作为栈上变量,自动释放,调用析构函数,同时释放锁。


 

c++ 封装线程库 0的更多相关文章

  1. c++ 封装线程库 2

    1.2线程回收: 首先得知道线程的两个状态: Joinable Detached 简单理解,如果一个线程是joinable的状态,那么这样的线程,就必须使用pthread_join来回收,否则程序结束 ...

  2. c++ 封装线程库 3

    1. 继承与重写run方法 我们封装了Thread类,并设置成员函数run()为纯虚函数,因此我们使用类继承,并重写run方法: class IncCount : public Thread//增加计 ...

  3. c++ 封装线程库 1

    1.Pthread条件变量简介 条件变量也是线程间同步一个重要的内容,如果说互斥是一个种竞争关系,那么条件变量用于协调线程之间的关系,是一种合作关系. 条件变量的应用很多,例如:BlockingQue ...

  4. 引擎之旅 Chapter.2 线程库

    预备知识可参考我整理的博客 Windows编程之线程:https://www.cnblogs.com/ZhuSenlin/p/16662075.html Windows编程之线程同步:https:// ...

  5. Linux posix线程库总结

    由于历史原因,2.5.x以前的linux对pthreads没有提供内核级的支持,所以在linux上的pthreads实现只能采用n:1的方式,也称为库实现. 线程的实现,经历了如下发展阶段: Linu ...

  6. Boost线程库学习笔记

    一.创建一个线程 创建线程 boost::thread myThread(threadFun); 需要注意的是:参数可以是函数对象或者函数指针.并且这个函数无参数,并返回void类型. 当一个thre ...

  7. 130行C语言实现个用户态线程库——ezthread

    准确的说是除掉头文件,测试代码和非关键的纯算法代码(只有双向环形链表的ADT),核心代码只有130行左右,已经是蝇量级的用户态线程库了.把这个库取名为ezthread,意思是,这太easy了,人人都可 ...

  8. 使用boost.python封装C++库

    使用boost.python封装C++库 C++以高性能著称,但是编写较为复杂.而简洁是Python的强项.如果能珠联璧合,就能发挥两家之长.本文尝试用boost库的python模块封装C++ 前期准 ...

  9. OS之进程管理---多线程模型和线程库(POSIX PTread)

    多线程简介 线程是CPU使用的基本单元,包括线程ID,程序计数器.寄存器组.各自的堆栈等,在相同线程组中,所有线程共享进程代码段,数据段和其他系统资源. 传统的的单线程模式是每一个进程只能单个控制线程 ...

随机推荐

  1. linux删除文件、创建文件

    1.删除文件 rm huahua.txt 2.创建文件 touch huahua.txt

  2. Entity Framework Tutorial Basics(26):Add Entity Graph

    Add Entity Graph using DbContext: Adding entity graph with all new entities is a simple task. We can ...

  3. 简单的使用rabbitmq的例子

    1.创建了两个项目 : (1).spring_cloud_rabbitmq_send 消息发送者 (2).spring_cloud_rabbitmq_receive  消息接受者 2. 添加rabbi ...

  4. postgre-sql语法

    //客户端查询 public void pgsearchclient(HttpContext context, string starttime, string endtime, int page, ...

  5. Mybatis环境搭建中的案例分析 及 如果自己编写DAO接口的实现类

    Mybatis环境搭建中的案例分析public static void main (String[] args) throws Exception { //读配置文件 //第一个: 使用类加载器,只能 ...

  6. D - Back and Forth(模拟)

    Problem Statement Dolphin resides in two-dimensional Cartesian plane, with the positive x-axis point ...

  7. Python-OpenCV中VideoCapture类的使用

    目录   主要记录Python-OpenCV中的VideoCapture类的使用:官方文档:   VideoCapture()是用于从视频文件.图片序列.摄像头捕获视频的类: #!/usr/bin/e ...

  8. ajaxs

    AJAX 是一种独立于 Web 服务器软件的浏览器技术.AJAX 基于下列 Web 标准:JavaScript XML HTML CSS 在 AJAX 中使用的 Web 标准已被良好定义,并被所有的主 ...

  9. Pyinstaller打包matplotlib.pyplot画图时提示无法找到Qt插件的解决办法

    This application failed to start because it could not find or load the Qt platform plugin "wind ...

  10. Ceph配置文件查看修改方式

    1.     修改ceph配置文件的方式有三种:(其中包含临时和永久生效) 1)      修改所有或者指定的进程 2)      修改当前服务器进程 3)      修改配置文件 Note:在线修改 ...