1. 程式人生 > >linux c/c++多執行緒程式設計

linux c/c++多執行緒程式設計

如何在linux 下c++中類的成員函式中建立多執行緒 linux系統中執行緒程式庫是POSIX pthread。POSIX pthread它是一個c的庫,用C語言進行多執行緒程式設計我這裡就不多說了,網上的例子很多。但是如何在C++的類中實現多執行緒程式設計呢?如果套用C語言中建立多執行緒的方式,在編譯的時候會出現...does not match `void*(*)(void*)..這樣的錯誤。出現這種情況的原因是,編譯器在處理C++和C檔案上是不同的,也就是說C++和C語言裡邊指標函式不等價。解決這種錯誤的方法 有兩種: 1、不要將執行緒函式定義為類的成員函式,但是在類的成員函式裡邊呼叫它。 例如: [test.h] #ifndef TEST_H #define TEST_H class test { public:     test();     ~test(); private:     void createThread(); }; #endif [test.cpp] test::test() {} test::~test() {} void *threadFunction() {     printf("This is a thread");     for(;;); } void test::createThread() {     pthread_t threadID;     pthread_create(&threadID, NULL, threadFunction, NULL); } [main.cpp] #inlcude "test.h" int main() {     test t;     t.createThead();     for(;;);     return 0; } 2、將執行緒函式作為類的成員函式,那麼必須宣告改執行緒函式為靜態的函式,並且該執行緒函式所引用的其他成員函式也必須是靜態的,如果要使用類的成員變數,則必須在建立執行緒的時候通過void *指標進行傳遞。 例如: 【test.h】 #ifndef TEST_H #define TEST_H class test { public:     test();     ~test(); private:     int p;     static void *threadFction(void *arg);     static void sayHello(int r);     void createThread(); }; #endif [test.cpp] test::test() {} test::~test() {} void *test::threadFunction(void *arg) {     int m = *(int *)arg;     sayHello(m);     for(;;); } void sayHello(int r) {     printf("Hello world %d!\n", r); } void test::createThread() {     pthread_t threadID;     pthread_create(&threadID, NULL, threadFunction, NULL); } [main.cpp] #inlcude "test.h" int main() {     test t;     t.createThead();     for(;;);     return 0; } ====================================================================================

 http://bigbossman.blogbus.com/logs/10761605.html

 Linux下的程式設計一直是C語言的天下,但老是用C感覺寫的很乏味。用面向物件方法程式設計,聽著都倍有面子。於是決定先在的這個專案用C++來寫。雖然不一定能“以C++的思想”來寫C++,少會有C++的樣子。


但是問題來了:我需要在程式中動態建立一個執行緒,而pthread不接受C++類的成員函式作為引數。

原因也很簡單,類成員是在類被例項化成為物件後才存在的,即在編譯時是不存在的,編譯器無法取得函式的確切入口地址,自然無法通過編譯。

照這個分析,如果把要呼叫的類成員函式宣告為靜態的,pthread_create就可以找到函式的地址了。但這樣一來的話,由於類中的靜態函式無法呼叫類的非靜態成員。執行緒函式的功能就受到了很大限制,也就沒有比要將其放在類中了。

最容易想到的解決方案就是寫個C函式,然後再C函式中呼叫C++物件的成員函式。

比如類為

class foo(){

    public :
        thread();

}

class *f;

void *bar(void *arg){

    f->thread();       

    return NULL;
}

int  main(){

    .........
    f=new foo();
    
    pthread_create(&tid,&tattr,bar,NULL);

}

顯然這種發法太笨了,而且物件只能是全域性的。

注意到執行緒函式bar可以有一個任意型別的指標作為引數,那我們何不將物件通過這個指標將物件變為bar的一個引數,從而讓我們的程式好看一些。

class foo(){

    public :
        thread();

}


void *bar(void *args){

    foo *f=(foo *)args;

    f.thread();       

    return NULL;
}

int  main(){

    .........
    foo *f=new foo();
    pthread_create(&tid,&tattr,bar,f);

}

如果把上述兩種方法結合起來即物件中的靜態函式+通過指標引數傳遞物件,那又會怎麼樣呢?

class foo(){

    public :
        int thread();

        static void *wrapper(void *args){
            foo *f=static_cast<foo *>(args);
            f->thread();
            return NULL;
        }

}


int  main(){

    .........
    foo *f=new foo();
    pthread_create(&tid,&tattr,foo::wrapper,&f);

}

這樣就比較規整了吧?

 其他參考網頁

 http://www.ibm.com/developerworks/cn/linux/l-cn-mthreadps/index.html

 http://www.cppblog.com/bigsml/archive/2006/09/07/12137.html