Posted on 2012-12-14 11:01
鑫龍 閱讀(212)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
linux編程
線程的分離狀態(tài)決定一個(gè)線程以什么樣的方式來(lái)終止自己。
線程的默認(rèn)屬性,一般是非分離狀態(tài),
這種情況下,原有的線程等待創(chuàng)建的線程結(jié)束。
只有當(dāng)pthread_join()函數(shù)返回時(shí),創(chuàng)建的線程才算終止,才能釋放自己占用的系統(tǒng)資源。
而分離線程沒(méi)有被其他的線程所等待,自己運(yùn)行結(jié)束了,線程也就終止了,馬上釋放系統(tǒng)資源。
程序員應(yīng)該根據(jù)自己的需要,選擇適當(dāng)?shù)姆蛛x狀態(tài)。
關(guān)于分離線程的一種用法(轉(zhuǎn))
講到分離線程,先得從僵尸進(jìn)程講起(抱歉,確實(shí)不知道線程是否有僵尸一說(shuō))。
關(guān)于僵尸進(jìn)程:一般情況下進(jìn)程終止的時(shí)候,和它相關(guān)的系統(tǒng)資源也并不是主動(dòng)釋放的,而是進(jìn)入一種通常稱為“僵尸”(zombie)的狀態(tài)。它所占有 的資源一直被系統(tǒng)保留,直到它的父進(jìn)程(如果它直接的父進(jìn)程先于它去世,那么它將被init進(jìn)程所收養(yǎng),這個(gè)時(shí)候init就是它的父進(jìn)程)顯式地調(diào)用 wait系列函數(shù)為其“收尸”。為了讓父進(jìn)程盡快知道它去世的消息,它會(huì)在它死去的時(shí)候通過(guò)向父進(jìn)程發(fā)送SIGCHLD信號(hào)的方式向其“報(bào)喪”。
所以一旦父進(jìn)程長(zhǎng)期運(yùn)行,而又沒(méi)有顯示wait或者waitpid,同時(shí)也沒(méi)處理SIGCHLD信號(hào),這個(gè)時(shí)候init進(jìn)程,就沒(méi)辦法來(lái)替子進(jìn)程來(lái)收尸。這個(gè)時(shí)候,子進(jìn)程就真的成了”僵尸“了。
同理:
如果一個(gè)線程調(diào)用了這個(gè)函數(shù),那么當(dāng)這個(gè)線程終止的時(shí)候,和它相關(guān)的系統(tǒng)資源將被自動(dòng)釋放,系統(tǒng)不用也不能用pthread_join()等待其退 出。有的時(shí)候分離線程更好些,因?yàn)樗鼭撛诘販p少了一個(gè)線程回收的同步點(diǎn),并且pthread_join()這個(gè)API確實(shí)也是相當(dāng)?shù)仉y用。
為了讓主線程省去去子線程收尸的過(guò)程,可以使用
int pthread_detach(pthread_t thread);
來(lái)讓子線程處于分離狀態(tài),就不需要父線程再pthread_join了。
我們來(lái)看一種分離線程的用法。上次別人問(wèn)道一種情況,我發(fā)現(xiàn)必須要分離子線程:
void* task1(void*);
void usr();
int p1;
int main()
{
p1=0;
usr(); //調(diào)用這個(gè)認(rèn)為是你的觸發(fā)函數(shù)
getchar();
return 1;
}
void usr()
{
pthread_t pid1;
pthread_attr_t attr;
/*這里做你的事情*/
if(p1==0)
{ pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //因?yàn)槟愕木€程不便于等待的關(guān)系,設(shè)置為分離線程吧
pthread_create(&pid1, &attr, task1, NULL);
}
}
void* task1(void *arg1)
{
p1=1; //讓子線程不會(huì)被多次調(diào)用
int i=0;
printf("thread1 begin./n");
for(i=0;i<100;i++)
{
sleep(2);
printf("At thread1: i is %d/n",i);
usr(); //繼續(xù)調(diào)用
}
pthread_exit();
}
我 們看到,在這里task1這個(gè)線程函數(shù)居然會(huì)多次調(diào)用其父線程里的函數(shù),顯然usr函數(shù)里,我們無(wú)法等待task1結(jié)束,反而task1會(huì)多次調(diào)用 usr,一旦我們?cè)趗sr里pthread_join,則在子線程退出前,有多個(gè)usr函數(shù)會(huì)等待,很浪費(fèi)資源。所以,此處,將task1設(shè)置為分離線程 是一種很好的做法。