本文最早發表於CUIT技術網,為本人原創,如需轉載請說明出處為本部落格(www.csllm.cn)或CUIT技術網(icuit.cn)
我們進行多線程編程,可以有多種選擇,可以使用WindowsAPI,如果你在使用GTK,也可以使用GTK實現了的線程庫,如果你想讓你的程式有更多的移植性你最好是選擇POSIX中的Pthread函數庫,我的程式是在Linux下寫的,所以我使用了Pthread庫(是不是很傷心,我知道有不少人期待的是WindowsAPI的,好吧,有機會以後再講那個,現在先把這一系列專題寫完 ^_^)
如果你用的是LINUX/UNIX/MacOSX,那麼我們已經可以開始了,如果你用的是WINDOWS,那麼你需要從網站上下載PTHREAD的WINDOWS開發包,所幸他非常的小。網站地址是http://sourceware.org/pthreads-win32/
先來看一個基本的例子:
程式碼
#include <pthread.h>
#include <iostream>
using namespace std;
void* tprocess1(void* args){
while(1){
cout << "tprocess1" << endl;
}
return NULL;
}
void* tprocess2(void* args){
while(1){
cout << "tprocess2" << endl;
}
return NULL;
}
int main(){
pthread_t t1;
pthread_t t2;
pthread_create(&t1,NULL,tprocess1,NULL);
pthread_create(&t2,NULL,tprocess2,NULL);
pthread_join(t1,NULL);
return 0;
}
在上面的例子中,我們首先加入了pthread.h檔案包含,這是所以pthread多線程程式所必須的,接著是iostream我們進行輸入輸出時要用到,接著就是兩個函數的定義,這和普通的函數沒有什麼區別,之所以寫成的
程式碼
void* tprocess1(void* args)
這樣的形式,完全是為了迎合pthread_create函數的參數類型,你也可以不這樣定義,只要在調用pthread_create建立線程的時候強制轉換一下指標類型就可以了。
這兩個函數將被用做線程的執行體,也就是說在兩個線程裡同時運行這兩個函數。
現在我們來看main函數,和pthread有關的調用都在這裡了。
pthread_t是線程結構,用來儲存線程相關資料,你也可以理解為是線程類型,聲明一個線程對象(變數)。
程式碼
pthread_t t1;
pthread_t t2;
這裡我們聲明了兩個線程變數t1,t2
程式碼
pthread_create(&t1,NULL,tprocess1,NULL);
pthread_create(&t2,NULL,tprocess2,NULL);
這兩句非常重要,pthread_create用來建立線程並啟動,他的原型是
程式碼
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg);
我們可以知道第一個參數是線程指標,第二參數是線程屬性指標,線程屬性pthread_attr_t用來指定線程優先順序等屬性,一般的情況下,我們沒有必要修改,使用預設屬性來構造線程,所以這裡一般取NULL,我們也是這樣做的,第三個參數是一個函數指標(函數指標?什麼東西,沒聽說過啊?……巨暈,好嘛,你複習一下C或是C++指標那部分吧)就是線程要執行的代碼,這裡我們分別要執行tprocess1 tprocess2就寫成了上面的樣子,這裡這個函數指標的類型定義是返回一個空類型指標,接收一個空類型指標參數的函數指標,如果你的函數不是這個定義,那就可以直接轉化一下就可以了。
寫完這兩行代碼,兩個線程就已經執行起來了,但是如果你省略了
程式碼
pthread_join(t1,NULL);
然後嘗試編譯運行程式的時候你會發現程式似乎什麼也沒幹就退出了,是的,那是因為程式的主線程退出的時候作業系統會關閉應用程式使用的所有資源,包括線程……所以在main函數結束前我們得想辦法讓程式停下來,pthread_join方法的功能就是等待線程結束,要等的線程就是第一個參數,程式會在這個地方停下來,直到線程結束,第二個參數用來接受線程函數的傳回值,是void**類型的指標,如果沒有傳回值,就直接設為NULL吧。
程式寫好了,我們怎麼編譯運行它呢?
如果你使用的是Linux:
在終端裡輸入
g++ thread.cpp -othread -lpthread
./thread
就可以完成程式的編譯及運行
如果你用的是VC:
在工程屬性裡加入開發包裡的幾個庫檔案
把那幾個DLL檔案放到你的工程路徑裡,也就是程式運行時候的工作路徑,這個在VC6和2005裡似乎不太一樣,如果你不確定,那就直接放到SYSTEM32裡吧。。。
下面的工作就非常簡單了
點運行,提示編譯,就確定,好了,結果出來了。。。
是不是感覺多線程如此的簡單,短短几行代碼就搞定了,我想你已經可以寫出一個簡單的多線程程式了吧,呵呵,其實問題沒有這麼簡單,多線程我們還要面對線程同步的問題,我會在下一個專題裡給大家講到。