1. 程式人生 > >執行緒退出和執行緒資源回收問題

執行緒退出和執行緒資源回收問題

最近專案中遇到迴圈8M的記憶體洩漏問題,排查後發現是由於特殊場景下使子執行緒異常退出,主執行緒發現子執行緒退出便再次建立執行緒,此時未回收退出執行緒的資源造成了記憶體洩漏,導致資料庫宿主機oom,此問題不僅導致記憶體洩漏,還會使執行緒控制代碼用完導致其他程序無法分配執行緒的風險。

下面來看看關於執行緒退出和執行緒資源回收的有關問題

執行緒退出有多種方式,如return,pthread_exit,pthread_cancel等;執行緒分為可結合的(joinable)和 分離的(detached)兩種,如果沒有在建立執行緒時設定執行緒的屬性為PTHREAD_CREATE_DETACHED,則執行緒預設是可結合的。

可結合的執行緒線上程退出後不會立即釋放資源,必須要呼叫pthread_join來顯式的結束執行緒。分離的執行緒線上程退出時系統會自動回收資源。

一、設定分離執行緒的幾種方法:

1.在建立執行緒時加上

pthread_attr_t attr;
pthread_t thread;
pthread_attr_init (&attr);pthread_attr_setdetachstat(&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread, &attr, &thread_function, NULL);


pthread_attr_destroy (&attr);
2.線上程中呼叫pthread_detach(pthread_self());

3.主執行緒中呼叫pthread_detach(pid),pid為子執行緒的執行緒號

要注意的是,設定為分離的執行緒是不能呼叫pthread_join的,呼叫後會出錯

二、可結合的執行緒的幾種退出方式

1. 子執行緒使用return退出,主執行緒中使用pthread_join回收執行緒

2.子執行緒使用pthread_exit退出,主執行緒中使用pthread_join接收pthread_exit的返回值,並回收執行緒

3.主執行緒中呼叫pthread_cancel,然後呼叫pthread_join回收執行緒


from:http://blog.csdn.net/skyflying2012/article/details/24655751

在寫網路伺服器程式時可能需要實現多執行緒接收多個客戶端的資料,我實現方式比較傻,死迴圈等待client的connect,connect之後建立thread,這樣其實有一個問題,伺服器程式需要長期執行,長時間執行緒的建立,執行緒資源的回收就是一個問題。

Linux系統中程式的執行緒資源是有限的,表現為對於一個程式其能同時執行的執行緒數是有限的。而預設的條件下,一個執行緒結束後,其對應的資源不會被釋放,於是,如果在一個程式中,反覆建立執行緒,而執行緒又預設的退出,則最終執行緒資源耗盡,程序將不再能建立新的執行緒。

解決這個問題,有2種方式,系統自動釋放執行緒資源,或者由另一個執行緒釋放該執行緒資源。

程序執行後,本身,也是一個執行緒,主執行緒,主執行緒和主執行緒建立的執行緒共享程序資源。不同於其他執行緒,在於主執行緒執行結束後,程式退出,所有程式建立的執行緒也會退出。

一 系統自動釋放
如果想線上程結束時,由系統釋放執行緒資源,則需要設定執行緒屬性為detach,是執行緒分離主執行緒

程式碼上,可以這樣表示:

pthread_t t;
pthread_attr_t a; //執行緒屬性
pthread_attr_init(&a);  //初始化執行緒屬性
pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);      //設定執行緒屬性
pthread_create( &t, &a, GetAndSaveAuthviewSDRStub, (void*)lp);                   //建立執行緒

二 由另一個執行緒將該資源釋放

程式碼上,可以這樣表示:

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。