zoukankan      html  css  js  c++  java
  • 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");
        }
    }

    4 另一种封装线程的方法 (线程回调函数)

    4.1 直接将要调用的函数指针传入去初始化一个线程。这样可以避免频繁修改线程的执行函数。

    4.2 这个线程类目前只可以接收C函数,如果是一个C++成员函数,那么他的指针是 void *(Test::*) (void*)
    后面使用一种工具bind,可以实现函数的转化 boost::bind

    #ifndef __THREAD_H_
    #define __THREAD_H__
    
    #include <pthread.h>
    
    class Thread{
        public:
            typedef void* (*ThreadCallback)(void*); //定义一个函数指针类型
            Thread(ThreadCallback callback_);
            void start();
            void join();
        private:
            ThreadCallback  callback_;
            pthread_t tid_;
    };
    
    
    
    
    #endif
    #include <iostream>
    #include "thread.h"
    using namespace std;
    
    void * func(void * arg){
        cout << " callback OK " << endl;
        return NULL;
    }
    
    int main(int argc, const char *argv[])
    {
        Thread th(func);
        th.start();
        th.join();
        return 0;
    }
    #include "thread.h"
    
    Thread::Thread(ThreadCallback callback)
        :callback_(callback),tid_(0)
    {
    }
    
    void Thread::start(){
        pthread_create(&tid_, NULL, callback_, NULL);
    }
    
    void Thread::join(){
        pthread_join(tid_, NULL);
    }
  • 相关阅读:
    接口中解决默认方法冲突
    继承中的访问域问题
    继承中的多态问题
    Java中方法的调用过程
    【JS】表格获取每一列方法
    【Git报错】 ! [rejected] master -> master (fetch first)
    【Vue】vue-cli配置proxyTable调用服务器接口
    layui监听多个radio事件
    【总结】display属性inline,block,inline-block
    【实例总结】fixed定位元素内部滚动显示
  • 原文地址:https://www.cnblogs.com/monicalee/p/3847532.html
Copyright © 2011-2022 走看看