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. 什么是MTU,如何检测和设置路由器MTU值

    最大传输单元(Maximum Transmission Unit,MTU)是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位).最大传输单元这个参数通常与通信接口有关(网络接口卡.串口 ...

  2. java全栈day33--html

    本天要完成6个任务,并且布局静态页面(首页)详细分为六个部分  如下 网站信息页面案例(字体标签.排版标签) 网站图片信息页面案例(图片标签) 网站友情链接页面案例(列表标签) 网站首页案例(表格标签 ...

  3. Mysql--连接查询

    内连接查询 意义:找到表和表之间的关系或者是桥梁.连接查询是查询两个或者两个以上的表时使用的. JOIN|CROSS JOIN| INNER JOIN    通过ON  连接条件(这三个方式都行)一般 ...

  4. Java的get请求-----接口测试

    package findyou.Interface; import java.net.HttpURLConnection; import java.net.URL; public class URLC ...

  5. STL 结构体 内部函数

    typedef struct Node { int val; string name; bool operator < (const Node &right) const { retur ...

  6. await 与 SynchronizationContext 关系

    static async Task DoStep() { //step 1 Debug.WriteLine("DoStep Start thread id: " + System. ...

  7. CENTOS 7 升级安装 Python 3.5

    写在前面的话 本文采取源码的方式安装 Python 3.5.2,如果是其它版本会有或多或少的差异,且写这篇的时候官网最新的是 Python 3.7,个人使用 3.5 就足够了,没必要更新到最新,否则出 ...

  8. GS70 使用 Linux 下面Oracle数据库时 设定 特定目录存储数据文件

    1. 创建目录 mkdir /cwdata 2. 修改目录属性 chown -R oracle:oinstall /cwdata chmod -R /cwdata 效果为: 创建数据库实例时的界面为: ...

  9. Mysql union

    union简单来说就是多表链接,主要是用于(模糊)查询,全库搜索 多表搜索需要先将需要查询的表用union连接,然后在每一个union后面添加上相同的where条件 菜鸟教程

  10. Angular2入门-架构总览

    ▓▓▓▓▓▓ 大致介绍 在3月23日,Angular4正式发布(没有3).似乎现在学Angular2又晚了,又晚一步-_-||.Angular2在Angular1的基础上有了较大的改变.之前向一个同学 ...