int pthread_detach(pthread_t thread);??? 成功:0;失敗:錯誤號
作用:從狀態上實現線程分離,注意不是指該線程獨自占用地址空間。
線程分離狀態:指定該狀態,線程主動與主控線程斷開關系。線程結束后(不會產生僵尸線程),其退出狀態不由其他線程獲取,而直接自己自動釋放(自己清理掉PCB的殘留資源)。網絡、多線程服務器常用。
進程若有該機制,將不會產生僵尸進程。僵尸進程的產生主要由于進程死后,大部分資源被釋放,一點殘留資源仍存于系統中,導致內核認為該進程仍存在。(注意進程沒有這一機制)
也可使用 pthread_create函數參2(線程屬性)來設置線程分離。
一般情況下,線程終止后,其終止狀態一直保留到其它線程調用pthread_join獲取它的狀態為止(或者進程終止被回收了)。但是線程也可以被置為detach狀態,這樣的線程一旦終止就立刻回收它占用的所有資源,而不保留終止狀態。不能對一個已經處于detach狀態的線程調用pthread_join,這樣的調用將返回EINVAL錯誤(22號錯誤)。也就是說,如果已經對一個線程調用了pthread_detach就不能再調用pthread_join了。
//使用pthread_detach函數實現線程分離
#include <stdio.h>
#include <stdlib.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;pthread_exit((void *)1);
}int main(void)
{pthread_t tid;void *tret;int err;#if 0pthread_attr_t attr; /*通過線程屬性來設置游離態(分離態)*/pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);pthread_create(&tid, &attr, tfn, NULL);#elsepthread_create(&tid, NULL, tfn, NULL);pthread_detach(tid); //讓線程分離 ----自動退出,無系統殘留資源#endifwhile (1) {err = pthread_join(tid, &tret);printf("-------------err= %d\n", err);if (err != 0)fprintf(stderr, "thread_join error: %s\n", strerror(err));elsefprintf(stderr, "thread exit code %d\n", (int)tret);sleep(1);}return 0;
}
[root@localhost 01_pthread_test]# ./pthrd_detach
-------------err= 22??? ???//可見錯誤號是22
thread count 2
thread_join error: Invalid argument? //錯誤號對應的詳細解釋
thread count 1
-------------err= 22
thread_join error: Invalid argument
-------------err= 22
thread count 0
thread_join error: Invalid argument
-------------err= 22
thread_join error: Invalid argument
-------------err= 22
thread_join error: Invalid argument
分析:
- 使用pthread_detach函數實現線程分離時,應當先創建線程(pthread_create),然后再用pthread_detach實現該線程的分離。因此,這種方式與修改線程屬性來實現線程分離的方法相比,不會發生在線程創建函數還未來得及返回時子線程提前結束導致返回的線程號是錯誤的線程號的情況。因為采用這種方法,即使子線程提前結束(先于pthread_create返回),但是子線程還未處于分離狀態,因此其PCB的殘留信息依然存在,如線程號等一些系統資源,所以線程號等系統資源仍被占據,還未分配出去,所以創建函數返回的線程號依然是該線程的線程號;
- 對處于分離狀態的線程進行回收,會出現錯誤,且錯誤編號為22;
- 還可采用修改線程屬性的方法來實現線程分離。