日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux系统编程---14(回收子线程,回收多个子线程,线程分离,杀死线程)

發(fā)布時間:2023/11/30 linux 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux系统编程---14(回收子线程,回收多个子线程,线程分离,杀死线程) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

回收子線程

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)
對比記憶:

  • 進(jìn)程中:main 返回值、exit 參數(shù)–>int;等待子進(jìn)程結(jié)束 wait 函數(shù)參數(shù)–>int*
  • 線程中:線程主函數(shù)返回值、pthread_exit-->void*;等待線程結(jié)束 pthread_join 函數(shù)參數(shù)–>void**
  • 對于進(jìn)程而言,wait函數(shù)的返回值是int,所以獲取退出值使用int*
  • 對于線程,void*作為函數(shù)返回值,回收使用void**
  • 示例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é)如下:

  • 如果 thread 線程通過 return 返回,retval 所指向的單元里存放的是 thread 線程函數(shù)的返回值。
  • 如果 thread 線程被別的線程調(diào)用 pthread_cancel 異常終止掉,retval 所指向的單元里存放的是常數(shù)PTHREAD_CANCELED。
  • 如果 thread 線程是自己調(diào)用 pthread_exit 終止的,retval 所指向的單元存放的是傳給 pthread_exit 的參數(shù)。
  • 如果對 thread 線程的終止?fàn)顟B(tài)不感興趣,可以傳 NULL 給 retval 參數(shù)。
  • 示例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;失敗:錯誤號

  • 線程分離狀態(tài):指定該狀態(tài),線程主動與主控線程斷開關(guān)系。線程結(jié)束后,其退出狀態(tài)不由其他線程獲取,而 直接自己自動釋放。網(wǎng)絡(luò)、多線程服務(wù)器常用。
  • 進(jìn)程若有該機(jī)制,將不會產(chǎn)生僵尸進(jìn)程。僵尸進(jìn)程的產(chǎn)生主要由于進(jìn)程死后,大部分資源被釋放,一點殘留資 源仍存于系統(tǒng)中,導(dǎo)致內(nèi)核認(rèn)為該進(jìn)程仍存在。
    也可使用 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á)某個取消點(檢查點)。

  • 類似于玩游戲存檔,必須到達(dá)指定的場所(存檔點,如:客棧、倉庫、城里等)才能存儲進(jìn)度。殺死線程也不是 立刻就能完成,必須要到達(dá)取消點。
  • 取消點:是線程檢查是否被取消,并按請求進(jìn)行動作的一個位置。通常是一些系統(tǒng)調(diào)用 creat,open,pause, close,read,write..... 執(zhí)行命令 man 7 pthreads 可以查看具備這些取消點的系統(tǒng)調(diào)用列表。也可參閱 APUE.12.7 取消選項小節(jié)。
    可粗略認(rèn)為一個系統(tǒng)調(diào)用(進(jìn)入內(nèi)核)即為一個取消點。如線程中沒有取消點,可以通過調(diào)用 pthreestcancel 函數(shù) 自行設(shè)置一個取消點。
  • 被取消的線程, 退出值定義在Linux的pthread庫中。常數(shù)PTHREAD_CANCELED的值是**-1**。可在頭文件pthread.h 中找到它的定義:#define PTHREAD_CANCELED((void*)-1)。因此當(dāng)我們對一個已經(jīng)被取消的線程使用 pthread_join 回收時,得到的返回值為-1。
  • 終止線程的三種方法
    /*三種退出線程的方法*/ #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)程,
    有三種方法:

  • 從線程主函數(shù) return。這種方法對主控線程不適用,從 main 函數(shù) return 相當(dāng)于調(diào)用 exit。
  • 一個線程可以調(diào)用 pthread_cancel 終止同一進(jìn)程中的另一個線程。
  • 線程可以調(diào)用 pthread_exit 終止自己。
  • 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)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。