在咱們使用默認屬性建立一個線程的時候,線程是 joinable 的。 joinable 狀態的線程,必須在另外一個線程中使用 pthread_join() 等待其結束, 若是一個 joinable 的線程在結束後,沒有使用 pthread_join() 進行操做, 這個線程就會變成"殭屍線程"。每一個殭屍線程都會消耗一些系統資源, 當有太多的殭屍線程的時候,可能會致使建立線程失敗。linux
下面是一個建立殭屍線程的例子:多線程
void* start_thread(void * arg) { //這個線程什麼也不作,直接退出 pthread_exit(NULL); return NULL; } int create_pthread(int n) { int try = 0; int i = 0; int err = 0; for(i = 0; i < n && try < 3; i++) { //當建立線程失敗的時候,嘗試3次 pthread_t pt; err = pthread_create(&pt, NULL, start_thread, NULL); if(0 != err) { if(EAGAIN == err) { printf("errno : [EAGAIN]\n"); } sleep(2); try ++; } } printf("create [%d] threads\n", i); return err; } int main(int argc, char * argv[]) { int n = 1 << 20;//最多建立 1M 個線程 create_pthread(n); return 0; }
上面代碼是建立殭屍線程的主要部分,把上面代碼編譯執行後, 輸出的結果是什麼呢:spa
errno : [EAGAIN] errno : [EAGAIN] errno : [EAGAIN] create [32754] threads
在上面的例子中,每一個線程開始後,什麼也不作,馬上就結束。 最後在個人環境下,只能建立 32754 個額外線程。線程
當線程被設置爲分離狀態後,線程結束時,它的資源會被系統自動的回收, 而再也不須要在其它線程中對其進行 pthread_join() 操做。code
下面咱們對代碼作一些修改,讓每一個線程在開始執行後,進行線程的分離, 而後看看執行後的結果。blog
void* start_thread(void * arg) { //注意,這裏執行了線程的分離操做。線程分離也能夠在線程建立的時候, //在屬性裏面設置 pthread_detach(pthread_self()); pthread_exit(NULL); return NULL; } int create_pthread(int n) { int try = 0; int i = 0; int err = 0; for(i = 0; i < n && try < 3; i++) { pthread_t pt; err = pthread_create(&pt, NULL, start_thread, NULL); if(0 != err) { if(EAGAIN == err) { printf("errno : [EAGAIN]\n"); } sleep(2); try ++; } } printf("create [%d] threads\n", i); return err; } int main(int argc, char * argv[]) { int n = 1 << 20; create_pthread(n); return 0; }
執行結果以下:資源
create [1048576] threads
能夠看到,最後成功建立了 1M 個線程。而沒有進行 pthread_join() 操做的時候,最多建立建立了 32754 個線程,緣由就是沒有 detach 的線程,在其結束後,一些系統分配給它的資源還在被佔用, 沒有被回收,致使沒法再建立新的線程了。而 detach 的線程,在其結束後, 它的資源會被系統進行回收,而後進行再利用。因此此次才能建立 1M 的線程。get
在 man pthread_create 手冊中,能夠看到關於一個線程的 detachd 狀態和 joinable 狀態的描述。其中說到,一個線程或者是 detachd 的狀態,這樣它結束後,資源會被系統 回收;或者是 joinable 狀態,而且在另外一個線程裏面被 pthread_join() 等待,pthread_join() 會回收它的資源。同步
咱們能夠再作個實驗,在建立完了一個 joinable 的線程後再使用 pthread_join() 等待它的結束, 回收它的資源,看看最多能夠建立多少個線程。it
void* start_thread(void * arg) { pthread_exit(NULL); return NULL; } int create_pthread(int n) { int try = 0; int i = 0; int err = 0; for(i = 0; i < n && try < 3; i++) { pthread_t pt; err = pthread_create(&pt, NULL, start_thread, NULL); if(0 != err) { if(EAGAIN == err) { printf("errno : [EAGAIN]\n"); } sleep(2); try ++; } void *st = NULL; //這裏等待一個線程的結束,並回收其資源 err = pthread_join(pt, &st); if(0 != err) { printf("errno = [%d]\n", err); sleep(2); try ++; } } printf("create [%d] threads\n", i); return err; } int main(int argc, char * argv[]) { int n = 1 << 20; create_pthread(n); return 0; }
執行結果:
create [1048576] threads
最後也是建立了 1M 個線程。
結論就是,在咱們編寫多線程應用的時候,或者把一個線程的屬性設置爲 detachd 的狀態,讓系統來回收它的資源;或者是 joinable 狀態,這樣就可使用 pthread_join() 來阻塞的等待一個線程的結束,並回收其資源,而且pthread_join() 還會獲得線程退出後的返回值,來判斷線程的退出狀態 。
同步地址:https://www.fengbohello.top/archives/linux-pthread-detach