pthread_detach函數
實現線程分離
?????? int pthread_detach(pthread_t thread);????? 成功:0;失敗:錯誤號
?????? 線程分離狀態:指定該狀態,線程主動與主控線程斷開關系。線程結束后,其退出狀態不由其他線程獲取,而直接自己自動釋放。網絡、多線程服務器常用。
?????? 進程若有該機制,將不會產生僵尸進程。僵尸進程的產生主要由于進程死后,大部分資源被釋放,一點殘留資源仍存于系統中,導致內核認為該進程仍存在。
?????? 也可使用 pthread_create函數參2(線程屬性)來設置線程分離。
【練習】:使用pthread_detach函數實現線程分離??????????????????????????????????????????????????????? ????????????? 【pthrd_detach.c】
一般情況下,線程終止后,其終止狀態一直保留到其它線程調用pthread_join獲取它的狀態為止。但是線程也可以被置為detach狀態,這樣的線程一旦終止就立刻回收它占用的所有資源,而不保留終止狀態。不能對一個已經處于detach狀態的線程調用pthread_join,這樣的調用將返回EINVAL錯誤。也就是說,如果已經對一個線程調用了pthread_detach就不能再調用pthread_join了。
/*** detach.c ***/ #include<unistd.h> #include<string.h> #include<pthread.h> #include<stdio.h>void *tfn(void *arg) {int n = 3;while(n--){printf("thread count %d\n",n);sleep(1);}pthread_exit((void*)1); }int main() {pthread_t tid;void* tret;int err;pthread_attr_t attr;pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);pthread_create(&tid,&attr,tfn,NULL);while(1){err = pthread_join(tid,&tret);printf("------------------- err = %d\n",err);if(0 != err){fprintf(stderr,"thread_join error : %s\n",strerror(err));}else{fprintf(stderr,"thread exit code %d\n",(int)tret);}sleep(1);}return 0; }
運行結果:
ubuntu1604@ubuntu:~/wangqinghe/linux/20190819$ ./detach
------------------- err = 22
thread_join error : Invalid argument
thread count 2
------------------- err = 22
thread_join error : Invalid argument
thread count 1
------------------- err = 22
thread_join error : Invalid argument
thread count 0
------------------- err = 22
thread_join error : Invalid argument
------------------- err = 22
thread_join error : Invalid argument
------------------- err = 22
thread_join error : Invalid argument
------------------- err = 22
thread_join error : Invalid argument
^C
pthread_cancel函數
殺死(取消)線程????????????????? 其作用,對應進程中 kill() 函數。
?????? int pthread_cancel(pthread_t thread); 成功:0;失敗:錯誤號
?????? 【注意】:線程的取消并不是實時的,而有一定的延時。需要等待線程到達某個取消點(檢查點)。
?????? 類似于玩游戲存檔,必須到達指定的場所(存檔點,如:客棧、倉庫、城里等)才能存儲進度。殺死線程也不是立刻就能完成,必須要到達取消點。
?????? 取消點:是線程檢查是否被取消,并按請求進行動作的一個位置。通常是一些系統調用creat,open,pause,close,read,write..... 執行命令man 7 pthreads可以查看具備這些取消點的系統調用列表。也可參閱 APUE.12.7 取消選項小節。
可粗略認為一個系統調用(進入內核)即為一個取消點。如線程中沒有取消點,可以通過調用pthreestcancel函數自行設置一個取消點。
被取消的線程,?? 退出值定義在Linux的pthread庫中。常數PTHREAD_CANCELED的值是-1。可在頭文件pthread.h中找到它的定義:#define PTHREAD_CANCELED ((void *) -1)。因此當我們對一個已經被取消的線程使用pthread_join回收時,得到的返回值為-1。
【練習】:終止線程的三種方法。注意“取消點”的概念。??????????????????????????????????????????????? ????????????? 【pthrd_endof3.c】
終止線程方式
總結:終止某個線程而不終止整個進程,有三種方法:
- 從線程主函數return。這種方法對主控線程不適用,從main函數return相當于調用exit。
- 一個線程可以調用pthread_cancel終止同一進程中的另一個線程。
- 線程可以調用pthread_exit終止自己
/*** pthread_endof3.c ***/#include <stdio.h> #include <unistd.h> #include <pthread.h> #include <stdlib.h>void *tfn1(void *arg) {printf("thread 1 returning\n");return (void *)111; }void *tfn2(void *arg) {printf("thread 2 exiting\n");pthread_exit((void *)222); }void *tfn3(void *arg) {while (1) {//printf("thread 3: I'm going to die in 3 seconds ...\n");//sleep(1); pthread_testcancel(); //自己添加取消點*/ }return (void *)666; }int main(void) {pthread_t tid;void *tret = NULL;pthread_create(&tid, NULL, tfn1, NULL);pthread_join(tid, &tret);printf("thread 1 exit code = %d\n\n", (int)tret);pthread_create(&tid, NULL, tfn2, NULL);pthread_join(tid, &tret);printf("thread 2 exit code = %d\n\n", (int)tret);pthread_create(&tid, NULL, tfn3, NULL);sleep(3);pthread_cancel(tid);pthread_join(tid, &tret);printf("thread 3 exit code = %d\n", (int)tret);return 0; }
ubuntu1604@ubuntu:~/wangqinghe/linux/20190819$ ./pthread_endof3
thread 1 returning
thread 1 exit code = 111
?
thread 2 exiting
thread 2 exit code = 222
?
thread 3 exit code = -1
?