天天看點

分離式線程

1、技術都是為了解決實際問題的,考慮下面的場景:
    主線程建立一個子線程,子線程做一些任務,在主線程上,等待子線程完成任務,然後向下運作。代碼如下:
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    void* FuncA(void* arg)
    {
        printf("FuncA Time[%d]\n", time(NULL));
        sleep(2);
    }
    
    int main(int argc,char* argv[])
    {
        pthread_t threadA;
        pthread_create(&threadA, NULL, FuncA, NULL);
    
        pthread_join(threadA,NULL);
        printf("main  Time[%d]\n", time(NULL));
        getchar();
        return 0;
    }
    
    [niu_zibin@localhost thread]$ g++ -o main main.cpp -lpthread
    [niu_zibin@localhost thread]$ ./main
    FuncA Time[1477297071]
    main  Time[1477297073]
2、可以看到,主線程阻塞在pthread_join,那麼問題來了,如何讓主線程不阻塞在pthread_join呢?
3、上面産生的原因是:預設建立的線程A不是分離的,也就是被主線程關聯。
    是以,解決辦法是:建立線程A的時候,把它設定成分離的,不再被别的線程關聯。如下:
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    void* FuncA(void* arg)
    {
        printf("First  FuncA Time[%d]\n", time(NULL));
        sleep(2);
        printf("Second FuncA Time[%d]\n", time(NULL));
    }
    
    int main(int argc,char* argv[])
    {
        pthread_t threadA;
        pthread_attr_t pAttr;
        pthread_attr_init(&pAttr);
        pthread_attr_setdetachstate(&pAttr,PTHREAD_CREATE_DETACHED);
        pthread_create(&threadA, &pAttr, FuncA, NULL);
    
        int ret = pthread_join(threadA,NULL);
        printf("pthread_join ret[%d]\n",ret);
        printf("main  Time[%d]\n", time(NULL));
        getchar();
        return 0;
    }
    
    [niu_zibin@localhost thread]$ g++ -o main main.cpp -lpthread
    [niu_zibin@localhost thread]$ ./main
    pthread_join ret[22]
    main  Time[1477298407]
    First  FuncA Time[1477298407]
    Second FuncA Time[1477298409]
    不再阻塞。
4、注意:設定了分離狀态【PTHREAD_CREATE_DETACHED】,pthread_join傳回錯誤。
    改成可結合狀态【PTHREAD_CREATE_JOINABLE】,pthread_join傳回成功,如下:
    pthread_attr_setdetachstate(&pAttr,PTHREAD_CREATE_JOINABLE);
    
    [niu_zibin@localhost thread]$ g++ -o main main.cpp -lpthread
    [niu_zibin@localhost thread]$ ./main 
    First  FuncA Time[1477298637]
    Second FuncA Time[1477298639]
    pthread_join ret[0]
    main  Time[1477298639]
5、還有一種辦法,就是建立線程A之後,也就是線上程A運作的時候,進行分離操作,如下:
    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    void* FuncA(void* arg)
    {
        printf("First  FuncA Time[%d]\n", time(NULL));
        sleep(2);
        printf("Second FuncA Time[%d]\n", time(NULL));
    }
    
    int main(int argc,char* argv[])
    {
        pthread_t threadA;
        pthread_create(&threadA, NULL, FuncA, NULL);
    
        pthread_detach(threadA);
        pthread_join(threadA,NULL);
        printf("main  Time[%d]\n", time(NULL));
        getchar();
        return 0;
    }
    
    [niu_zibin@localhost thread]$ g++ -o main main.cpp -lpthread
    [niu_zibin@localhost thread]$ ./main
    main  Time[1477298924]
    First  FuncA Time[1477298924]
    Second FuncA Time[1477298926]
6、線程是可結合(joinable)或者分離的(detached)。
    對于可結合線程A,被主線程回收資源(比如A的線程棧)和殺死,在主線程join線程A之前,線程A的資源是不會被釋放的。
    對于分離式線程A,在它終止後,系統會自動釋放線程A的資源。
7、對于分離式線程A,考慮一種極端的情況,分離式線程執行特别快,在pthread_create傳回之前就已經終止了。
    這就意味着,pthread_create傳回的資料是垃圾資料。
8、怎麼解決上面的問題?
    在分離式線程A中執行pthread_cond_timewait函數,讓目前線程等待一會,確定pthread_create傳回的時候,目前線程還沒有終止。
    還有一種辦法,使用PV操作,分離式線程内先執行P操作,卡在這裡。在主線程pthread_create之後進行V操作,
    進而確定pthread_create之後,分離式線程剛開始執行。