1. 程式人生 > >C++ 在類裡面使用多執行緒技術

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; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

如上所示,程式碼聲明瞭一個類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; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

以上程式碼通過呼叫lanch()來建立多執行緒來執行insert_pth,insert_pth 再呼叫insert(). 但是 這樣的程式碼在編譯時即會報錯。

pthread.cpp: In member functionvoid Test::lanch()’:
pthread.cpp:30:42: error: invalid use of non-static member function
  pthread_create(&pth,NULL,insert_pth,NULL);
  • 1
  • 2
  • 3
  • 4

只需將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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

總結

使用多執行緒處理耗時成員函式的步驟: 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()函式內容不要呼叫類的其它成員函式,否則成員函式將無法獲取正確的this指標而操作錯誤記憶體,從而導致segmantation fault.
  • 1
					<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-8cccb36679.css" rel="stylesheet">
            </div>