C++封装POSIX 线程库线程的封装

Posted NearXDU

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++封装POSIX 线程库线程的封装相关的知识,希望对你有一定的参考价值。

C++封装POSIX 线程库(三)线程的封装

1.POSIX 线程简介

POSIX 提供以下函数:

1.1线程创建:

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);

//返回:成功为0 失败为错误码

我们注意第3个参数是一个函数指针,它返回void * 参数也是void *,这就是所谓线程,第四个参数则是线程的参数,通常情况下,我们可能会这样写代码:

void *mythread(void *arg)

    //tasks...


int main()

    pthread_t tid1;
    pthread_create(&tid1,NULL,mythread,NULL);
    //main thread
    pthread_join(tid1, NULL);

这里直接用函数名指代回调函数,也可以加上取地址符&

1.2线程回收:

首先得知道线程的两个状态:

Joinable
Detached

简单理解,如果一个线程是joinable的状态,那么这样的线程,就必须使用pthread_join来回收,否则程序结束时,线程所占用的资源不会释放,就会造成内存泄漏。我们通常在主进程中会阻塞调用pthread_join来等待我们的线程结束。

如果是Detached状态的线程,那么在线程结束后,资源会自动释放,POSIX pthread线程库中,提供下面函数来让线程进入Detached状态:

#include <pthread.h>
int pthread_detach(pthread_t thread);

在我们的设计中,考虑pthread_joinpthread_detach的特性,分别对成员函数join和析构函数进程封装。

线程创建时默认情况情况下是Joinable状态。

1.3示例:

通常只需注意线程的创建与回收即可,例如:

#include<iostream>  
#include<pthread.h>  
#include <unistd.h>
using namespace std;  

void * child1(void * arg)  
  
    pthread_t tid =pthread_self();  
    cout<<"thread "<<(unsigned int )tid<<" enter"<<endl;  
    //tasks
    cout<<"thread "<<tid<<" return"<<endl;  
  
int main(void)  
  
    pthread_t tid1;  
    cout<<"hello main thread"<<endl;  
    pthread_create(&tid1,NULL,child1,NULL);  
    pthread_join(tid1,NULL);
    cout<<"main thread exit"<<endl;  
    return 0;  

  

2.线程封装

封装为一个C++ 类需要一些技巧:

1.Thread是没有拷贝构造和赋值语义的,因此也需要继承自boost::noncopyable
2.关于pthread_create的第三个参数(返回void*参数为void*的函数指针),因为成员函数会隐式包含this指针作为参数,所以加以static修饰。
3.对于pthread_create的第四个参数(void *arg作为线程参数),传入this指针方便线程调用成员函数。
4.使用join()成员函数封装pthread_join(),析构函数使用pthread_detach()处理。
5.设置run()成员函数为纯虚函数,子类重写run()方法。

声明如下:

#ifndef __THREAD_H__
#define __THREAD_H__
#include <iostream>
#include <boost/noncopyable.hpp>
#include <pthread.h>
#include "MutexLock.h"
#include "Condition.h"
class Thread : public boost::noncopyable

    public :
        Thread();
        virtual ~Thread();//虚析构
        void start();
        void join();
        virtual void run()=0;//纯虚函数
        pthread_t getThreadId() const
        
            return threadId_;
        
    private:
        //pthread_create()第三个参数是一个回调函数,void*为返回值和参数
        static void *runInThread(void *arg);
        pthread_t threadId_;
        bool isRunning_;
;
#endif

这里对成员函数进行定义,run()由于是纯虚函数,我们放到子类中重写:

#include "Thread.h"


Thread::Thread():isRunning_(false),threadId_(0)//构造函数
Thread::~Thread()//析构函数

    if(isRunning_)
    
        CHECK(!pthread_detach(threadId_));//如果线程正在运行,则让其状态为detached
    


void *Thread::runInThread(void *arg)

    Thread *pt =static_cast<Thread*>(arg);//arg即为this指针
    pt->run();//调用run方法
    return NULL;



void Thread::start()

    CHECK(!pthread_create(&threadId_,NULL,Thread::runInThread,this));//创建线程
    isRunning_=true;


void Thread::join()

    assert(isRunning_);
    CHECK(!pthread_join(threadId_,NULL));//回收线程
    isRunning_=false;

3.参考

1.http://www.cnblogs.com/inevermore/p/4008572.html
2.《Linux多线程服务端编程—使用muduo C++ 网络库》


以上是关于C++封装POSIX 线程库线程的封装的主要内容,如果未能解决你的问题,请参考以下文章

Linux posix线程库总结

Android 线程池的封装

线程操作C++封装

如何将C / C ++库代码封装为可在具有多个实例的单独线程中运行?

Linux篇第十五篇——多线程(生产消费模型+POSIX信号量)

Linux篇第十五篇——多线程(生产消费模型+POSIX信号量)