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_join
和pthread_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 线程库线程的封装的主要内容,如果未能解决你的问题,请参考以下文章
如何将C / C ++库代码封装为可在具有多个实例的单独线程中运行?