2012年3月8日 星期四

pthread使用說明

轉自:http://www.cnblogs.com/xianghang123/archive/2011/08/11/2134927.html


linux下C/C++,多線程pthread 


 ·線程創建 


  函數原型:int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr,void *(*start_rtn)(void),void *restrict arg); 


  返回值:若是成功建立線程返回0,否則返回錯誤的編號。 


  形式參數:pthread_t *restrict tidp要創建的線程的線程id指針;const pthread_attr_t *restrict attr創建線程時的線程屬性;void* (start_rtn)(void)返回值是void類型的指針函數;void *restrict arg start_rtn的形參。 


  ·線程掛起:該函數的作用使得當前線程掛起,等待另一個線程返回才繼續執行。也就是說當程序運行到這個地方時,程序會先停止,然後等線程id為thread的這個線程返回,然後程序才會斷續執行。 


  函數原型:int pthread_join( pthread_t thread, void **value_ptr); 


  參數說明如下:thread等待退出線程的線程號;value_ptr退出線程的返回值。 


  ·線程退出 


  函數原型:void pthread_exit(void *rval_ptr); 


  ·獲取當前線程id 


  函數原型:pthread_t pthread_self(void); 


  ·互斥鎖 


  創建pthread_mutex_init;銷毀pthread_mutex_destroy;加鎖pthread_mutex_lock;解鎖pthread_mutex_unlock。 


  ·條件鎖 


  創建pthread_cond_init;銷毀pthread_cond_destroy;觸發pthread_cond_signal;廣播pthread_cond_broadcast S;等待pthread_cond_wait。  


  ·正確處理Linux平台下的線程結束問題 


  在Linux平台下,當處理線程結束時需要注意的一個問題就是如何讓一個線程善始善終,讓其所占資源得到正確釋放。在Linux平台默認情況下,雖然各個線程之間是相互獨立的,一個線程的終止不會去通知或影響其他的線程。但是已經終止的線程的資源並不會隨著線程的終止而得到釋放,我們需要調用pthread_join() 來獲得另一個線程的終止狀態並且釋放該線程所占的資源。








【用C】


/* example.c*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void thread(void)
{
int i;
for(i=0;i<3;i++){
sleep(1);
printf("This is a pthread.\n");}
}
int main(void)
{
pthread_t id;
int i,ret;
ret=pthread_create(&id,NULL,(void *) thread,NULL);
if(ret!=0){
printf ("Create pthread error!\n");
exit (1);
}
for(i=0;i<3;i++){
printf("This is the main process.\n");
sleep(1);
}
pthread_join(id,NULL);
return (0);
}





編譯命令 gcc -o example example.c -lpthread


注:【1】pthread 庫不是 Linux 系統默認的庫,連接時需要使用靜態庫 libpthread.a,所以在使用pthread_create()創建線程,以及調用 pthread_atfork()函數建立fork處理程序時,需要鏈接該庫。


      【2】還要添加頭文件pthread.h


      【3】因為C庫自帶sleep,所以可以不添加unistd.h頭文件





【用C++】


/* example.cpp*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void *thread(void *ptr)
{
int i;
for(i=0;i<3;i++){
sleep(1);
printf("This is a pthread.\n");}
}
int main(void)
{
pthread_t id;
int i,ret;
ret=pthread_create(&id,NULL,thread,NULL);
if(ret!=0){
printf ("Create pthread error!\n");
exit (1);
}
for(i=0;i<3;i++){
printf("This is the main process.\n");
sleep(1);
}
pthread_join(id,NULL);
return (0);
}





編譯鏈接命令 g++ -o example2 example.c -lpthread





【注】 標亮部分,注意C++開發時與C的區別,解釋如下:


我們注意在Posix定義建立線程函數的原型:
extern int pthread_create (pthread_t *__restrict __threadp,
                           __const pthread_attr_t *__restrict __attr,
                           void *(*__start_routine) (void *),
                           void *__restrict __arg) __THROW;
這個call中的第三個參數是載入一個函數,這個函數有一個參數可以傳入,返回一個 通用指針。
我們再來看看原來函數中是怎樣調用這一原型的,基本上就是類似一下的調用方式:
(void *) thread 或是 (void *) &thread


這個表達式的含義:取一個指向函數main_thread的指針,然後將其轉換為一個通用指針。
這就是說顯然上述兩個事情並非同一個事情,故而正確的調用方式是
ret=pthread_create(&id,NULL,thread,NULL);
處理函數的定義如下:
void *thread(void *ptr)
值得注意的是在gcc編譯時不會出錯,但是用g++就會有問題:invalid conversion from `void*' to `void*(*)(void*),究其原因就是C語言編譯器允許隱含性的將一個通用指針轉換為任意類型的指針,而C++不允許。

沒有留言:

張貼留言