linux c/c++多執行緒程式設計
阿新 • • 發佈:2019-02-09
如何在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;
}
====================================================================================
但是問題來了:我需要在程式中動態建立一個執行緒,而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://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