pthread join和detach

//從別處拷貝過來的,只做爲本身查看方便,原做者不詳,請諒解。  一:關於join  join  join是三種同步線程的方式之一。另外兩種分別是互斥鎖(mutex)和條件變量(condition variable)。  調用pthread_join()將阻塞本身,一直到要等待加入的線程運行結束。  能夠用pthread_join()獲取線程的返回值。  一個線程對應一個pthread_join()調用,對同一個線程進行屢次pthread_join()調用是邏輯錯誤。  join or detach  線程分兩種:一種能夠join,另外一種不能夠。該屬性在建立線程的時候指定。  joinable線程可在建立後,用pthread_detach()顯式地分離。但分離後不能夠再合併。該操做不可逆。  爲了確保移植性,在建立線程時,最好顯式指定其join或detach屬性。彷佛不是全部POSIX實現都是用joinable做默認。  二: pthread_detach  建立一個線程默認的狀態是joinable, 若是一個線程結束運行但沒有被join,則它的狀態相似於進程中的Zombie Process,即還有一部分資源沒有被回收(退出狀態碼),因此建立線程者應該調用pthread_join來等待線程運行結束,並可獲得線程的退出代碼,回收其資源(相似於wait,waitpid)  可是調用pthread_join(pthread_id)後,若是該線程沒有運行結束,調用者會被阻塞,在有些狀況下咱們並不但願如此,好比在Web服務器中當主線程爲每一個新來的連接建立一個子線程進行處理的時候,主線程並不但願由於調用pthread_join而阻塞(由於還要繼續處理以後到來的連接),這時能夠在子線程中加入代碼  pthread_detach(pthread_self())  或者父線程調用  pthread_detach(thread_id)(非阻塞,可當即返回)  這將該子線程的狀態設置爲detached,則該線程運行結束後會自動釋放全部資源。  三:pthread_join  調用pthread_join的線程會阻塞,直到指定的線程返回,調用了pthread_exit,或者被取消。      若是線程簡單的返回,那麼rval_ptr被設置成線程的返回值,參見範例1;若是調用了pthread_exit,則可將一個無類型指針返回,在pthread_join中對其進行訪問,參見範例2;若是線程被取消,rval_ptr被設置成PTHREAD_CANCELED。      若是咱們不關心線程的返回值,那麼咱們能夠把rval_ptr設置爲NULL。  範例1:  #include <pthread.h>  #include <string.h>  void *thr_fn1(void *arg)  {      printf(「thread 1 returning.\n」);      return((void *)1);  }  void *thr_fn2(void *arg)  {      printf(「thread 2 exiting.\n」);      return((void *)2);  }  int main()  {      pthread_t tid1,tid2;      void *tret;      pthread_create(&tid1,NULL,thr_fn1,NULL);      pthread_create(&tid2,NULL,thr_fn2,NULL);      pthread_join(tid1,&tret);      printf(「thread 1 exit code %d\n」,(int)tret);      pthread_join(tid2,&tret);      printf(「thread 2 exit code %d\n」,(int)tret);      exit(0);  }  運行結果:  thread 1 returning.  thread 1 exit code 1.  thread 2 exiting.  thread 2 exit code 2.  範例2:  #include <stdio.h>  #include <pthread.h>  void thread1(char s[])  {          printf("This is a pthread1.\n");          printf("%s\n",s);          pthread_exit("Hello first!");  //結束線程,返回一個值。  }  void thread2(char s[])  {          printf("This is a pthread2.\n");          printf("%s\n",s);          pthread_exit("Hello second!");  }  int main(void)  {          pthread_t id1,id2;          void *a1,*a2;          int i,ret1,ret2;          char s1[]="This is first thread!";          char s2[]="This is second thread!";          ret1=pthread_create(&id1,NULL,(void *) thread1,s1);          ret2=pthread_create(&id2,NULL,(void *) thread2,s2);          if(ret1!=0){                  printf ("Create pthread1 error!\n");                  exit (1);          }          pthread_join(id1,&a1);          printf("%s\n",(char*)a1);          if(ret2!=0){                  printf ("Create pthread2 error!\n");                  exit (1);          }          printf("This is the  main process.\n");          pthread_join(id2,&a2);          printf("%s\n",(char*)a2);          return (0);  }  運行結果:  [****@XD**** c]$ ./example  This is a pthread1.  This is first thread!  Hello first!  This is the main process.  This is a pthread2.  <參考資料語>  通常狀況下,進程中各個線程的運行都是相互獨立的,線程的終止並不會通知,也不會影響其餘線程,終止的線程所佔用的資源也並不會隨着線程的終止而獲得釋 放。正如進程之間能夠用wait()系統調用來同步終止並釋放資源同樣,線程之間也有相似機制,那就是pthread_join()函數  pthread_join()的調用者將掛起並等待th線程終止,retval是pthread_exit()調用者線程(線程ID爲th)的返回值,如 果thread_return不爲NULL,則*thread_return=retval。須要注意的是一個線程僅容許惟一的一個線程使用 pthread_join()等待它的終止,而且被等待的線程應該處於可join狀態,即非DETACHED狀態  若是進程中的某個線程執行了pthread_detach(th),則th線程將處於DETACHED狀態,這使得th線程在結束運行時自行釋放所佔用的 內存資源,同時也沒法由pthread_join()同步,pthread_detach()執行以後,對th請求pthread_join()將返回錯誤  一個可join的線程所佔用的內存僅當有線程對其執行了pthread_join()後纔會釋放,所以爲了不內存泄漏,全部線程的終止,要麼已設爲DETACHED,要麼就須要使用pthread_join()來回收  3) 主線程用pthread_exit仍是return  用pthread_exit只會使主線程自身退出,產生的子線程繼續執行;用return則全部線程退出。  綜合以上要想讓子線程總能完整執行(不會中途退出),一種方法是在主線程中調用pthread_join對其等待,即pthread_create/pthread_join/pthread_exit或return;一種方法是在主線程退出時使用pthread_exit,這樣子線程能繼續執行,即pthread_create/pthread_detach/pthread_exit;還有一種是pthread_create/pthread_detach/return,這時就要保證主線程不能退出,至少是子線程完成前不能退出。如今的項目中用的就是第三種方法,主線程是一個死循環,子線程有的是死循環有的不是。  <參考資料語>  理論上說,pthread_exit()和線程宿體函數退出的功能是相同的,函數結束時會在內部自動調用pthread_exit()來清理線程相關的資源。但實際上兩者因爲編譯器的處理有很大的不一樣。  在進程主函數(main())中調用pthread_exit(),只會使主函數所在的線程(能夠說是進程的主線程)退出;而若是是return,編譯器將使其調用進程退出的代碼(如_exit()),從而致使進程及其全部線程結束運行。 
相關文章
相關標籤/搜索