您的位置:首页 > 编程语言 > C语言/C++

C/C++ pthread 线程库的封装

2015-11-23 18:12 477 查看
经常没事写一些服务器压力测试的工具,如http,mysql,等。说到压力测试,首先想到的应该就是多线程,研究过一段时间的pthread,包括线程锁,在这里发一个自己写的Posix封装,可用于很多需要使用到多线程的情景当中。

Posix.h
Posix应该把它当成一个父类,写一个子类继承他,并重写action方法,action()为所有的线程所执行的内容,最后使用Run()开始执行所有线程。
#ifndef POSIX_H_
#define POSIX_H_

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>

using namespace std;

class Posix {
public:
Posix();
int getThreadNumber(void);  //获取线程数
int pthreadMutexInit(void);  //初始化线程锁,如果不希望使用锁可以不用,有关锁的更多,在后面介绍
int pthreadMutexLock(void);  //加锁
int pthreadMutexUnlock(void); //解锁
int pthreadMutexDestroy(void); //销毁锁
void setThreadNumber(int threadNumber); //设置开启的线程数
void Run();                    //所有线程开始执行
virtual void action()=0;        //每个线程执行的内容,在子类中重写
protected:
/*线程数*/
int _threadNumber;
/*线程锁*/
pthread_mutex_t _mutex;
};

#endif /* POSIX_H_ */


Posix.cpp
因为pthread_create()函数只接收函数指针,不接受C++成员函数,所以另外创建静态函数actionRun()作为桥接。
#include "Posix.h"

Posix::Posix(){
//初始化线程数为8
_threadNumber = 8;
}

static void* actionRun(void* parm){
Posix* pt = (Posix*)parm;
pt->action();    //执行子类重写的虚函数
return NULL;
}

/*线程锁初始化函数*/
int Posix::pthreadMutexInit(void){
return pthread_mutex_init(&this->_mutex,NULL);
}

/*线程加锁*/
int Posix::pthreadMutexLock(void){
return pthread_mutex_lock(&this->_mutex);
}

/*线程解锁*/
int Posix::pthreadMutexUnlock(void){
return pthread_mutex_unlock(&this->_mutex);
}

/*销毁锁*/
int Posix::pthreadMutexDestroy(void){
return pthread_mutex_destroy(&this->_mutex);
}

int Posix::getThreadNumber(void){
return this->_threadNumber;
}
void Posix::setThreadNumber(int threadNumber){
this->_threadNumber = threadNumber;
}

void Posix::Run(){
pthread_t pthread[this->_threadNumber]; //线程数组
for ( int count = 1 ; count <= this->_threadNumber ; count++ ){ //开始创建线程

//在此,因为pthread_create的第三个参数只接收函数指针,C++成员函数不能进行传递,所以创建actionRun为普通的静态函数,作为桥接,具体实现请往上看actionRun();
if ( pthread_create( &pthread[count] , NULL , actionRun , this) != 0 ){
cerr << "线程创建失败,线程号 = " << count <<endl;
}
}
for ( int count = 1 ; count <= this->_threadNumber ; count++ ){
if ( pthread_join( pthread[count], NULL ) != 0 ){
cerr << "线程执行失败,线程号 = " << count << endl;
}
}
//	cout << "线程执行完成!" << endl;
}


上面是Posix父类的定义与实现,下面我们写一个新的test类来继承Posix类
test.h
重写父类action()函数,把要做的事写上,这里我们打印每个线程的ID
#ifndef TEST_H_
#define TEST_H_

#include "Posix.h"

class test : public Posix {
public:
action(){
cout << pthread_self() << endl; //打印线程ID
}
}

#endif /* TEST_H_ */


下面是main.cpp
#include "test.h"
int main(void){
test* mytest = new test();

mytest->setThreadNumber(10); //设置线程数为10
mytest->Run();
return 0;
}
执行结果:




下面是有关线程锁的介绍。
在线程执行时,所有的线程是并发执行的,我们不希望线程之间抢占同一资源,如多个线程对同一个FILE指针进行写操作,这样会出现莫名其妙的问题,这时我们就要使用线程锁,所以在main.cpp中我们用pthreadMutexInit()方法来初始化一下线程锁
#include <iostream>
#include "test.h"

using namespace std;

int main(void){
test* mytest = new test();
mytest->pthreadMutexInit(); //初始化锁
mytest->setThreadNumber(10);
mytest->Run();
mytest->pthreadMutexDestroy(); //销毁锁
return 0;
}


同样的,在每个线程执行的过程当中,当进行到某个步骤的时候,我们也可以为其设置加锁和解锁,例如所有线程需要对一个成员变量进行操作时,我们可以在其操作之前加锁,操作完成后解锁。
#ifndef TEST_H_
#define TEST_H_

#include "Posix.h"

class test : public Posix {
public:
test();
virtual ~test();
void action(){
this->pthreadMutexLock();    //锁住线程,形成队列,先到的先执行
cout << pthread_self() << endl; //打印线程ID
this->pthreadMutexUnlock();  //解锁线程
}
};

#endif /* TEST_H_ */


最后编译时别忘了添加编译选项: -lpthread
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息