from:http://blog.csdn.net/skyflying2012/article/details/24655751及相關論壇 html
http://blog.chinaunix.net/uid-29783732-id-4485673.html linux
在寫網絡服務器程序時可能須要實現多線程接收多個客戶端的數據,我實現方式比較傻,死循環等待client的connect,connect以後建立thread,這樣其實有一個問題,服務器程序須要長期運行,長時間線程的建立,線程資源的回收就是一個問題。windows
Linux系統中程序的線程資源是有限的,表現爲對於一個程序其能同時運行的線程數是有限的。而默認的條件下,一個線程結束後,其對應的資源不會被釋放,因而,若是在一個程序中,反覆創建線程,而線程又默認的退出,則最終線程資源耗盡,進程將再也不能創建新的線程。服務器
解決這個問題,有2種方式,系統自動釋放線程資源,或者由另外一個線程釋放該線程資源。網絡
進程運行後,自己,也是一個線程,主線程,主線程和主線程創建的線程共享進程資源。不一樣於其餘線程,在於主線程運行結束後,程序退出,全部程序創建的線程也會退出。多線程
一 系統自動釋放
若是想在線程結束時,由系統釋放線程資源,則須要設置線程屬性爲detach,是線程分離主線程函數
代碼上,能夠這樣表示:ui
pthread_t tid;
pthread_attr_t attr; //線程屬性
pthread_attr_init(&attr); //初始化線程屬性
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //設置線程屬性
pthread_create( &tid, &attr, run, NULL); //創建線程spa
二 由另外一個線程將該資源釋放.net
代碼上,能夠這樣表示:
pthread_t t;
pthread_create( NULL, NULL, GetAndSaveAuthviewSDRStub, (void*)lp);
pthread_join( t);
pthread_join( t)等待線程t退出,並釋放t線程所佔用的資源。
pthread_join函數會阻塞等待指定線程退出,而後回收資源,這樣就有同步的功能,使一個線程等待另外一個線程退出,而後才繼續運行,可是對於服務器程序若是主線程在新建立的線程工做時還須要作別的事情,這種方法不是很好,就須要使用方法一
linux線程執行和windows不一樣,pthread有兩種狀態joinable狀態和unjoinable狀態,若是線程是joinable狀態,當線程函數本身返回退出時或pthread_exit時都不會釋放線程所佔用堆棧和線程描述符(總計8K多)。只有當你調用了pthread_join以後這些資源纔會被釋放。
如果unjoinable狀態的線程,這些資源在線程函數退出時或pthread_exit時自動會被釋放。
unjoinable屬性能夠在pthread_create時指定,或在線程建立後在線程中pthread_detach本身,如:pthread_detach(pthread_self()),將狀態改成unjoinable狀態,確保資源的釋放。或者將線程置爲joinable,而後適時調用pthread_join.
還有2個函數能夠實現線程的分離,pthread_detach(threadid)和pthread_detach(pthread_self())。
這2個函數區別是調用他們的線程不一樣,沒其餘區別。
pthread_detach(threadid)函數的功能是使線程ID爲threadid的線程處於分離狀態,一旦線程處於分離狀態,該線程終止時底層資源當即被回收;不然終止子線程的狀態會一直保存(佔用系統資源)直到主線程調用pthread_join(threadid,NULL)獲取線程的退出狀態。
一般是主線程使用pthread_create()建立子線程之後,通常能夠調用pthread_detach(threadid)分離剛剛建立的子線程,這裏的threadid是指子線程的threadid;如此以來,該子線程止時底層資源當即被回收;
被建立的子線程也能夠本身分離本身,子線程調用pthread_detach(pthread_self())就是分離本身,由於pthread_self()這個函數返回的就是本身自己的線程ID。
注:在分離屬性狀況下,一個線程結束時會當即釋放它所佔有的系統資源,但有一點要注意的是,若是設置一個線程分離屬性,而這個線程又運行得很是快的話,那麼它極可能在pthread_create函數返回以前就終止了線程函數的運行,它終止之後就頗有可能將線程號和系統資源移交給其餘的線程使用,這時調用pthread_create的線程就獲得錯誤的線程號。