新闻  |   论坛  |   博客  |   在线研讨会
C++ 在类里面使用多线程技术
电子禅石 | 2022-01-05 16:34:01    阅读:9291   发布文章

C++ 在类里面使用多线程技术

前言

有很多时候,我们希望可以在C++类里面对那些比较耗时的函数使用多线程技术,但是熟悉C++对象语法的人应该知道,C++类的成员函数的函数指针不能直接做为参数传到pthread_create,主要因为是C++成员函数指针带有类命名空间,同时成员函数末尾是会被C++编译器加上可以接收对象地址的this指针参数。因此需要将成员函数做一定的转化,将其转化为不被编译器加上this指针,而由我们自己来为该函数维护”this”指针即可。

举例:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <time.h>
using namespace std;
class Test
{
    public:
        int sum=0;
        int cnt;
    public:
        int insert();
};
int Test::insert()
{
    sleep(2);
    cnt+=1;
}


如上所示,代码声明了一个类Test,假设该类有一个十分耗时的成员函数:insert(),这个求和函数每次执行需要2000ms的时间。对于如此耗时的函数,我们在设计时都会想方法将其设计为线程函数,这样调用者才不会阻塞。 
于是我们为其加上多线程:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
using namespace std;
class Test
{
    public:
        int sum=0;
        int cnt;
    public:
        int insert();
        void * insert_pth(void*);
        void lanch();
};
int Test::insert()
{
    sleep(2);
    sum+=1;
}
void * Test::insert_pth(void*)
{
    insert();
}
void Test::lanch()
{
    pthread_t pth;
    pthread_create(&pth,NULL,insert_pth,NULL);
}
int main()
{
    Test t;
    t.lanch();
    return 0;
}

以上代码通过调用lanch()来创建多线程来执行insert_pth,insert_pth 再调用insert(). 
但是 这样的代码在编译时即会报错。

pthread.cpp: In member function ‘void Test::lanch()’:
pthread.cpp:30:42: error: invalid use of non-static member function
  pthread_create(&pth,NULL,insert_pth,NULL);


只需将insert_pth变化为static函数,同时将insert逻辑代码转移到insert_pth即可

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
using namespace std;
class Test
{
    public:
        int sum=0;
        int cnt;
    public:
        int insert();
    static  void * insert_pth(void*);
        void lanch();
};
int Test::insert()
{
    sleep(2);
    sum+=1;
    printf("%d insert.....\n",sum);
}
void * Test::insert_pth(void* __this)
{
    Test * _this =(Test *)__this;
    sleep(2);
    _this->sum+=1;
    printf("%d insert.....\n",_this->sum);
}
void Test::lanch()
{
    pthread_t pth;
    pthread_create(&pth,NULL,insert_pth,(void*)this);
}
int main()
{
    Test t;
    t.sum=0;
    t.lanch();
    sleep(5);
    return 0;
}

总结

使用多线程处理耗时成员函数的步骤: 
1. 声明另外一个静态函数:static void XXX_pth(void __this); 
该函数与目标成员函数在函数名尽量保持一致 
2. 将原成员函数的代码拷贝至void * XXX_pth(void * __this); 
在 XXX_pth()开始处将void * __this 转化为 对象的指针 ObjectPoint _this; 
将拷贝下来的所有成员变量加上_this-> 
3. 编写线程启动代码。 
注意pthread_create()最后一个参数传入this指针

注意

在 XXX_pth()函数内容不要调用类的其它成员函数,否则成员函数将无法获取正确的指针而操作错误内存,从而导致segmantation fault.

在C++的类中,普通成员函数不能作为pthread_create的线程函数,如果要作为pthread_create中的线程函数,必须是static !

        在C语言中,我们使用pthread_create创建线程,线程函数是一个全局函数,所以在C++中,创建线程时,也应该使用一个全局函数。static定义的类的成员函数就是一个全局函数。

 

更多 参考  http://blog.csdn.net/ksn13/article/details/40538083 


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

class Thread
{
    private:
        pthread_t pid;
    private:
        static void * start_thread(void *arg);// //静态成员函数
    public: 
        int start();
        virtual void run() = 0; //基类中的虚函数要么实现,要么是纯虚函数(绝对不允许声明不实现,也不纯虚)
};

int Thread::start()
{
    if(pthread_create(&pid,NULL,start_thread,(void *)this) != 0) //´创建一个线程(必须是全局函数)
    {    
        return -1; 
    }    
    return 0;
}

void* Thread::start_thread(void *arg) //静态成员函数只能访问静态变量或静态函数,通过传递this指针进行调用
{
    Thread *ptr = (Thread *)arg;
    ptr->run();  //线程的实体是run
}



class MyThread:public Thread
{
    public: 
        void run();
};
void MyThread::run()
{
    printf("hello world\n");
}

int main(int argc,char *argv[])
{
    MyThread myThread;
    myThread.start();
    //test.run();
    sleep(1);
    return 0;
}

编译运行:

diego@ubuntu:~/myProg/pthreadCpp$ g++ main.cpp -lpthread
diego@ubuntu:~/myProg/pthreadCpp$ ./a.out 
hello world
diego@ubuntu:~/myProg/pthreadCpp$


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
属于自己的技术积累分享,成为嵌入式系统研发高手。
推荐文章
最近访客