Linux系统编程---14(回收子线程,回收多个子线程,线程分离,杀死线程)
回收子線程
pthread_join 函數(shù)
阻塞等待線程退出,獲取線程退出狀態(tài) 其作用,對應(yīng)進(jìn)程中 waitpid() 函數(shù)。
int pthread_join (pthread_t thread,void** retval);成功:0,失敗:錯誤號
參數(shù):thread:線程ID(注意 :不是指針);retval:存儲線程結(jié)束狀態(tài)
對比記憶:
示例1
#include<stdio.h> #include<stdlib.h> #include<pthread.h>typedef struct{int a;int b; }exit_t;void * tfn(void *arg) //子線程函數(shù) {//子線程函數(shù)中定義 ret;exit_t *ret; //用結(jié)構(gòu)體定義一個變量ret=malloc(sizeof(exit_t));ret->a = 100;ret->b = 300;//返回ret 這個值,線程退出pthread_exit((void *)ret); }int main(void) {pthread_t tid;exit_t *retval;pthread_create(&tid,NULL,tfn,NULL);/*調(diào)用pthread_join可以獲取線程退出狀態(tài)*///第一個回收線程ID,第二個回收退出的值 pthread_join(tid,(void **)&retval); //wait(&status);printf("a = %d,b = %d\n",retval->a,retval->b);return 0; }注意事項
調(diào)用該函數(shù)的線程將掛起等待,直到 id 為 thread 的線程終止。 thread 線程以不同的方法終止,通過 pthread_join 得到的終止?fàn)顟B(tài)是不同的,總結(jié)如下:
示例2
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<pthread.h> #include<string.h>typedef struct {char ch;int var;char str[64]; }exit_t;void *thrd_func(void *arg) {//創(chuàng)建結(jié)構(gòu)體變量exit_t * retvar = (exit_t *)malloc(sizeof(exit_t));//賦值retvar->ch='m';retvar->var = 200;strcpy(retvar->str,"我的返回值");//子線程退出pthread_exit((void *)retvar);}int main(void) {pthread_t tid;int ret;exit_t * retval;//主控線程IDprintf(" In main1 id = %lu,pid = %u\n",pthread_self(),getpid());ret = pthread_create(&tid,NULL,thrd_func,NULL);if(ret != 0){fprintf(stderr,"pthread_create error:%s\n",strerror(ret));exit(1);}pthread_join(tid,(void **)&retval);printf("子線程返回值為\n");printf("ch = %c ,var = %d,str = %s\n",retval->ch,retval->var,retval->str);pthread_exit((void *)1);return 0; }使用 pthread_join 函數(shù)將循環(huán)創(chuàng)建的多個子線程回收。
/*回收多個子線程*/ #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<pthread.h>int var=100;void *tfn(void *arg) //每個子線程進(jìn)行回收 {int i;i = (int)arg;sleep(i); //輸出有順序if(i == 1){var = 333;printf("var = %d\n",var);return (void *)var;}else if(i == 3){var = 777;printf("I'm %d th 線程,線程ID為 %lu var = %d\n",i+1,pthread_self(),var);pthread_exit((void *)var);}else {printf("I'm %d th 線程,線程ID = %lu\n var = %d\n",i+1,pthread_self(),var);pthread_exit((void *)var);}return NULL; }int main(void) {pthread_t tid[5];int i;int *ret[5]; //保存 5個線程的退出值for(i = 0;i < 5; i++)//循環(huán)創(chuàng)建多個子線程pthread_create(&tid[i],NULL,tfn,(void*)i);for(i=0;i < 5; i++){ //對多個子線程進(jìn)行回收pthread_join(tid[i],(void **)&ret[i]);printf("-----------%d th ret = %d\n",i,(int)ret[i]);}printf("I'm main 線程 tid = %lu\t var = %d\n",pthread_self(),var);//主控線程也打印777,原因是共享全局變量sleep(i);return 0; }線程分離
pthread_detach 函數(shù)
進(jìn)程當(dāng)中沒有
實現(xiàn)線程分離
int pthread_detach(pthread_t thread); 成功:0;失敗:錯誤號
也可使用 pthread_create 函數(shù)參 2(線程屬性)來設(shè)置線程分離。
使用 pthread_detach 函數(shù)實現(xiàn)線程分離
#include<stdio.h> #include<unistd.h> #include<string.h> #include<pthread.h>void *tfn(void *arg) {int n=3;while(n--){printf("thread count %d\n",n);sleep(1);} return (void *)1; }int main(void) {pthread_t tid;void *tret;int err;pthread_create(&tid,NULL,tfn,NULL);pthread_detach(tid); //讓線程分離 ----自動退出,無系統(tǒng)殘留資源while(1){err = pthread_join(tid,&tret);printf("---------err= %d\n",err);if(err != 0)fprintf(stderr,"thread error: %s\n",strerror(err)); elsefprintf(stderr,"thread exit code %d\n",(int)tret);sleep(1);} return 0; }注意事項
一般情況下,線程終止后,其終止?fàn)顟B(tài)一直保留到其它線程調(diào)用 pthread_join 獲取它的狀態(tài)為止。但是線程也 可以被置為 detach 狀態(tài),這樣的線程一旦終止就立刻回收它占用的所有資源,而不保留終止?fàn)顟B(tài)。**不能對一個已 經(jīng)處于 detach 狀態(tài)的線程調(diào)用 pthread_join,這樣的調(diào)用將返回 EINVAL 錯誤。**也就是說,如果已經(jīng)對一個線程調(diào)用 了 pthread_detach 就不能再調(diào)用 pthread_join 了。
殺死線程
pthread_cancel 函數(shù)
殺死(取消)線程 其作用,對應(yīng)進(jìn)程中 kill() 函數(shù)。
int pthread_cancel(pthread_t thread); 成功:0;失敗:錯誤號
注意:線程的取消并不是實時的,而有一定的延時。需要等待線程到達(dá)某個取消點(檢查點)。
可粗略認(rèn)為一個系統(tǒng)調(diào)用(進(jìn)入內(nèi)核)即為一個取消點。如線程中沒有取消點,可以通過調(diào)用 pthreestcancel 函數(shù) 自行設(shè)置一個取消點。
終止線程的三種方法
/*三種退出線程的方法*/ #include<stdio.h> #include<string.h> #include<pthread.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\n",(int)tret);return 0; }
當(dāng)把一個線程殺死后,它的返回值是-1;
終止線程方式
總結(jié):終止某個線程而不終止整個進(jìn)程,
有三種方法:
pthread_equal 函數(shù)
比較兩個線程 ID 是否相等。
int pthread_equal (pthread_t t1,pthread_t t2); 有可能 Linux 在未來線程 ID pthread_t 類型被修改為結(jié)構(gòu)體實現(xiàn)。
總結(jié)
以上是生活随笔為你收集整理的Linux系统编程---14(回收子线程,回收多个子线程,线程分离,杀死线程)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 创世神话玉虚宫用什么法宝比较好?
- 下一篇: Linux系统编程----15(线程与进