線程分離

未分離線程

在咱們使用默認屬性建立一個線程的時候,線程是 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

join 後的線程

在 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

相關文章
相關標籤/搜索