0714-----C++Primer听课笔记----------封装mutex,thread,condition等

1.封装Mutex

1.1 封装前先总结一下常用的mutex操作有:

pthread_mutex_init(&mutex, NULL ); //初始化一个互斥锁

pthread_mutex_destroy(&mutex); //销毁一个互斥锁

pthread_mutex_lock(&mutex); //上锁

pthread_mutex_unlock(&mutex);// 解锁

1.2 用类把这下常用函数进行封装,代码如下,注意编译时不要忘记链接pthread。

#ifndef __MUTEXLOCK_H__
#define __MUTEXLOCK_H__

#include <pthread.h>
#include <stdexcept>

class Mutexlock{
    public:
        Mutexlock(){
            if(pthread_mutex_init(&mutex_, NULL)){
                throw std::runtime_error("init mutexlock error");
            }
        }

        ~Mutexlock(){
            if(pthread_mutex_destroy(&mutex_)){
                throw std::runtime_error("destroy mutexlock error");
            }
        }

        void lock(){
            if(pthread_mutex_lock(&mutex_)){
                throw std::runtime_error("lock muexlock errror");
            }
        }

        void unlock(){
            if(pthread_mutex_unlock(&mutex_)){
               throw std::runtime_error("unlock mutexlock error");
            }
        }

    private:
        pthread_mutex_t  mutex_;
};

#endif

2. 封装thread

2.1 thread线程要用的:函数有:

pthread_create(&tid, NULL, pthfunc,NULL);//创建一个线程

pthread_join(&tid);   //回收一个线程的资源

pthread_detach(tid);   //是系统自动回收线程资源

2.2 类的普通成员函数的函数指针包含类名。例如 void* (Thread::)(void*)。

#ifndef __THREAD_H__
#define __THREAD_H__

#include <pthread.h>

class Thread{
    public:
        Thread();
        ~Thread();

        void start();
        static void *thread_func(void *arg);
        void run();

    private:
        pthread_t tid_;
        int a_;
};

#endif
#include "thread.h"
#include <iostream>

using namespace std;

Thread::Thread()
    :tid_(-1){
}

Thread::~Thread(){
    pthread_join(tid_, NULL);
}

void Thread::start(){
    pthread_create(&tid_, NULL, thread_func, this);
}

void *Thread::thread_func(void *arg){
    Thread *pt = static_cast<Thread *>(arg);
    pt->run();
}

void Thread::run(){
    cout << "my run " << endl;
    a_ = 10;
    cout << "a_ = " << a_ << endl;
}

2.3 Thread的封装问题:

a) 函数指针问题,解决方案是使用static方法。

b) 上述方案的缺点是线程中无法访问对象的私有数据。

c) 解决方案是把对象的this指针当做线程参数传入。

3.封装条件变量

3.1条件变量常用的函数有

pthread_cond_init(&empty); //初始化一个条件变量

pthread_cond_wait(&empty, &mutex); //等待某个条件

pthread_cond_signal(&empty);//唤醒一个等待该条件的线程

pthread_cond_broadcast(&empty);//唤醒所有等待该条件的线程

3.2代码

#ifndef __CONDITION_H__
#define __CONDITION_H__

#include <pthread.h>

class Mutexlock; //使用类的引用 因此采用前向声明即可

class Condition{
    public:
        Condition(Mutexlock &lock);
        ~Condition();

        void wait();
        void notify();
        void notifyAll();

    private:
        pthread_cond_t  cond_;
        Mutexlock &lock_;

};

#endif
#include "condition.h"
#include <stdexcept>
#include "mutexlock.h" //这里调用了mutexlock中的getMutexptr()函数 因此要加头文件

Condition::Condition(Mutexlock &lock)
    :lock_(lock)
{
    if(pthread_cond_init(&cond_, NULL) != 0){
        throw std::runtime_error("init failed");
    }
}

Condition::~Condition(){
    if(pthread_cond_destroy(&cond_) != 0){
        throw std::runtime_error("destroy failed");
    }
}

void Condition::wait(){
    if(pthread_cond_wait(&cond_, lock_.getMutexptr()) != 0){
        throw std::runtime_error("wait failed");
    }
}

void Condition::notify(){
    if(pthread_cond_signal(&cond_) != 0){
       throw std::runtime_error("signal failed");
    }
}

void Condition::notifyAll(){
    if(pthread_cond_broadcast(&cond_) != 0){
        throw std::runtime_error("broadcast failed");
    }
}

0714-----C++Primer听课笔记----------封装mutex,thread,condition等

时间: 2024-10-10 09:28:43

0714-----C++Primer听课笔记----------封装mutex,thread,condition等的相关文章

0715-----C++Primer听课笔记----------疯狂封装之生产者与消费者

1.程序框架分析: a)首先将mutex, condition, queue 封装成各自的类,方便对外提供接口函数,这里要注意 condition的封装,一个条件变量和一把锁是一起用的,因此在初始化 condition 对象的时候要用一个 mutex 对象去初始化,在pthread_cond_wait函数中还要用到互斥锁中的指针,因此在mutex 类中要封装一个返回相应类型的函数.此外多个条件变量一般是和同一互斥锁进行交互,因此要在condition 中的  mutex对象设为引用,这里可以这样

0722-----C++Primer听课笔记----------虚函数和模板

1.虚指针和虚函数表 1.1 不含有任何数据成员或者虚函数的class或者struct大小为1,含有虚函数的对象在基地址部分有一个vptr,指向虚函数表,因此大小为4个字节. 1.2 动态绑定的原理:假设派生类和基类存在覆盖的关系(基类中定义了虚函数),那么派生类在虚函数表中,会覆盖掉基类相应的虚函数.当程序执行的时候,根据基类指针找到vptr,根据vptr找到vtable,然后找到相应的版本去执行.所以执行的是覆盖的版本,而具体被哪个版本覆盖是由具体的对象类型所决定的,所以才实现了根据对象的具

0722-----C++Primer听课笔记----------句柄类和智能指针

1.再说智能指针 1.1  为什么要用智能指针?对于一个指针,它指向一个动态分配内存的对象,若同时有多个指针指向该对象,那么当我们delete的时候,就会出现delete 一个无效内存的错误,因为该对象已经被delete过了,所以这就造成了错误.针对这一情况,我们想到,new 和 delete 必须是成对出现的,那么联想到类里面,很容易想到这个构造函数和析构函数也是成对出现的,对于每一个对象,初始化的时候会调用构造函数,而销毁的时候必然要调用析构函数.因此我们就可以对 指针 进行封装,将该指针的

0801-----C++Primer听课笔记----------C++11新特性 function 和 bind 的简单使用

1.function 和 函数指针 1.1 function有函数指针的功能,但是使用起来明显比函数指针更加灵活和方便. 1.2 函数指针和function的用法实例. 1.2.1 函数指针首先要清楚函数指针的类型,如void (*)(int, char)等,然后声明一函数指针变量直接调用即可. #include <iostream> using namespace std; /* * 函数指针的用法 */ void test(int i,double j){ cout << i

0718-----C++Primer听课笔记----------运算符重载

0.两个要点 a) 一个空类,编译器自动合成默认无参构造函数.析构函数.拷贝构造函数.赋值运算符. b) 在编写类的时候,必须严格区分对象是否可复制. 1.运算符重载之 string类 1.1 运算符重载的几个要点: a) 运算符重载可以有成员函数和友元函数的形式,后者比前者多一个参数. b) =和+=必须重载为成员函数的形式(不太理解原因). c) 输入和输出必须为友元函数的形式.而且输入操作符要考虑输入失败的情况. d) 运算符重载为成员函数的形式,那么该操作符的第一个操作数必然为该类的对象

0716-----C++Primer听课笔记----------STL之顺序容器、迭代器

1. 顺序容器的初始化操作 1.1 顺序容器(vector,list,deque)的五种初始化方法,以 vector 为例. #include <iostream> #include <string> #include <vector> using namespace std; int main(int argc, const char *argv[]) { //1.定义空数组 然后后面追加 vector<string> vec1; vec1.push_ba

0713-----C++Primer听课笔记----------类和对象

1.要求:将一篇文章录入,然后实现查询: a)查询可以输入字符或者字符串 b)将包含它们的单词输出 c)允许重复 d)如果输入查询有空格,当多个处理 Ex: 输入ro,应该打印出“microsift” 输入”he wr”,则查询两次 1.1  不用类实现 #include <iostream> #include <string> #include <vector> #include <fstream> #include <stdexcept> u

0715-----C++Primer听课笔记-----------函数指针 、单例模式

1.函数指针 1.1 普通成员函数指针包含类名信息以及const属性,指向具体函数是必须加上&符号. #include <iostream> using namespace std; class Test{ public: void setValue(const string &s, int a){ s_ = s; a_ = a; } void print() const{ cout << s_ << endl << a_ <<

0712-----C++Primer听课笔记----------IO流

0.不要试着从C++编译器的角度理解问题,而是从程序的语义着手. 1.控制台标准输入输出流的使用 1.1IO对象不可复制或者赋值.因此使用IO对象做参数必须使用非const 引用参数(非const因为对IO对象的读写会改变其状态). 1.2当cin输入非法数据时,fail置为1,当cin遇到文件结尾(ctrl+D)时, fail和eof都为1. #include <iostream> #include <string> #include <vector> using n