天天看點

2、Linux多線程,線程的分離與結合

(2)線程的分離與結合

    在任何一個時間點上,線程是可結合的(joinable),或者是分離的(detached)。一個可結合的線程能夠被其他線程收回其資源和殺死;在被其他線程回收之前,它的存儲器資源(如棧)是不釋放的。相反,一個分離的線程是不能被其他線程回收或殺死的,它的存儲器資源在它終止時由系統自動釋放。

線程的分離狀态決定一個線程以什麼樣的方式來終止自己。在上面的例子中,我們采用了線程的預設屬性,即為非分離狀态(即可結合的,joinable,需要回收),這種情況下,原有的線程等待建立的線程結束;隻有當pthread_join()函數傳回時,建立的線程才算終止,才能釋放自己占用的系統資源。而分離線程不是這樣子的,它沒有被其他的線程所等待,自己運作結束了,線程也就終止了,馬上釋放系統資源。程式員應該根據自己的需要,選擇适當的分離狀态。

設定線程分離狀态的函數為pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)。第二個參數可選為PTHREAD_CREATE_DETACHED(分離線程)和 PTHREAD _CREATE_JOINABLE(非分離線程)。這裡要注意的一點是,如果設定一個線程為分離線程,而這個線程運作又非常快,它很可能在pthread_create函數傳回之前就終止了,它終止以後就可能将線程号和系統資源移交給其他的線程使用,這樣調用pthread_create的線程就得到了錯誤的線程号。要避免這種情況可以采取一定的同步措施,最簡單的方法之一是可以在被建立的線程裡調用pthread_cond_timewait函數,讓這個線程等待一會兒,留出足夠的時間讓函數pthread_create傳回。設定一段等待時間,是在多線程程式設計裡常用的方法。但是注意不要使用諸如wait()之類的函數,它們是使整個程序睡眠,并不能解決線程同步的問題。

另外一個可能常用的屬性是線程的優先級,它存放在結構sched_param中。用函數pthread_attr_getschedparam和函數pthread_attr_setschedparam進行存放,一般說來,我們總是先取優先級,對取得的值修改後再存放回去。

4)線程等待——正确處理線程終止

#include <pthread.h>

void pthread_exit(void *retval);

void pthread_join(pthread_t th,void *thread_return);//挂起等待th結束,*thread_return=retval;

int pthread_detach(pthread_t th);

    如果線程處于joinable狀态,則隻能隻能被建立他的線程等待終止。

    在Linux平台預設情況下,雖然各個線程之間是互相獨立的,一個線程的終止不會去通知或影響其他的線程。但是已經終止的線程的資源并不會随着線程的終止而得到釋放,我們需要調用 pthread_join() 來獲得另一個線程的終止狀态并且釋放該線程所占的資源。(說明:線程處于joinable狀态下)

    調用該函數的線程将挂起,等待 th 所表示的線程的結束。 thread_return 是指向線程 th 傳回值的指針。需要注意的是 th 所表示的線程必須是 joinable 的,即處于非 detached(遊離)狀态;并且隻可以有唯一的一個線程對 th 調用 pthread_join() 。如果 th 處于 detached 狀态,那麼對 th 的 pthread_join() 調用将傳回錯誤。

    如果不關心一個線程的結束狀态,那麼也可以将一個線程設定為 detached 狀态,進而讓作業系統在該線程結束時來回收它所占的資源。将一個線程設定為detached 狀态可以通過兩種方式來實作。一種是調用 pthread_detach() 函數,可以将線程 th 設定為 detached 狀态。另一種方法是在建立線程時就将它設定為 detached 狀态,首先初始化一個線程屬性變量,然後将其設定為 detached 狀态,最後将它作為參數傳入線程建立函數 pthread_create(),這樣所建立出來的線程就直接處于 detached 狀态。

建立 detach 線程:

    pthread_t       tid;

    pthread_attr_t  attr;

    pthread_attr_init(&attr);

    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    pthread_create(&tid, &attr, THREAD_FUNCTION, arg);

    總之為了在使用 pthread 時避免線程的資源線上程結束時不能得到正确釋放,進而避免産生潛在的記憶體洩漏問題,在對待線程結束時,要確定該線程處于 detached 狀态,否着就需要調用 pthread_join() 函數來對其進行資源回收。 

繼續閱讀