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


Posix.h

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

#ifndef POSIX_H_
#define POSIX_H_

#include 
#include 
#include 
#include 

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 <_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;
}

执行结果:

C/C++ pthread 线程库的封装_第1张图片



下面是有关线程锁的介绍。

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

#include 
#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