天天看點

【多線程程式設計學習筆記5】擷取線程函數的傳回值:pthread_join() 函數

申明:本學習筆記是在該教程的基礎上結合自己的學習情況進行的總結,不是原創,想要看原版的請看C語言中文網的多線程程式設計(C語言+Linux),該網站有很多好的程式設計學習教程,尤其是關于C語言的。

前面提到,如果我們想擷取某個線程執行結束時傳回的資料,可以調用 pthread_join() 函數來實作。本節,我們就為您詳細講解 pthread_join() 函數的功能和用法。

pthread_join() 函數聲明在

<pthread.h>

頭檔案中,文法格式如下:

int pthread_join(pthread_t thread, void ** retval);
           

thread 參數用于指定接收哪個線程的傳回值;retval 參數表示接收到的傳回值,如果 thread 線程沒有傳回值,又或者我們不需要接收 thread 線程的傳回值,可以将 retval 參數置為 NULL。

pthread_join() 函數會一直阻塞調用它的線程,直至目标線程執行結束(接收到目标線程的傳回值),阻塞狀态才會解除。(如果是主線程調用pthread_join(),那麼會阻塞主線程,等目标線程執行結束,主線程的阻塞狀态才會解除)

如果 pthread_join() 函數成功等到了目标線程執行結束(成功擷取到目标線程的傳回值),傳回值為數字 0;反之如果執行失敗,函數會根據失敗原因傳回相應的非零值,每個非零值都對應着不同的宏,例如:

  • EDEADLK:檢測到線程發生了死鎖。關于線程發生死鎖,我們會在《Linux如何避免線程發生死鎖?》一節中做詳細講解。
  • EINVAL:分為兩種情況,要麼目标線程本身不允許其它線程擷取它的傳回值,要麼事先就已經有線程調用 pthread_join() 函數擷取到了目标線程的傳回值。
  • ESRCH:找不到指定的 thread 線程。
以上這些宏都聲明在 <errno.h> 頭檔案中,如果程式中想使用這些宏,需提前引入此頭檔案。

再次強調,一個線程執行結束的傳回值隻能由一個 pthread_join() 函數擷取,當有多個線程調用 pthread_join() 函數擷取同一個線程的執行結果時,哪個線程最先執行 pthread_join() 函數,執行結果就由那個線程獲得,其它線程的 pthread_join() 函數都将執行失敗。

對于一個預設屬性的線程 A 來說,線程占用的資源并不會因為執行結束而得到釋放。而通過在其它線程中執行

pthread_join(A,NULL);

語句,可以輕松實作“及時釋放線程 A 所占資源”的目的。

接下來通過一個樣例,給大家示範 pthread_join() 函數的用法:

#include <stdio.h>
#include <errno.h>   //使用宏 ESRCH
#include <pthread.h>
//線程執行的函數
void *ThreadFun(void *arg)
{
    pthread_exit("http://c.biancheng.net");//指針類型轉換,從char*->void*
}
int main()
{
    int res;
    void * thread_result;
    pthread_t myThread;
    //建立 myThread 線程
    res = pthread_create(&myThread, NULL, ThreadFun, NULL);
    if (res != 0) {
        printf("線程建立失敗");
        return 0;
    }
    //阻塞主線程,等待 myThread 線程執行結束
    res = pthread_join(myThread, &thread_result);
    if (res != 0) {
        printf("1:等待線程失敗");
    }
    //輸出擷取到的 myThread 線程的傳回值
    printf("%s\n", (char*)thread_result);//指針類型轉換,從void*->char*
    //嘗試再次擷取 myThread 線程的傳回值
    res = pthread_join(myThread, &thread_result);
    if (res == ESRCH) {
        printf("2:等待線程失敗,線程不存在");
    }
    return 0;
}
           
【多線程程式設計學習筆記5】擷取線程函數的傳回值:pthread_join() 函數

在程式的在主線程(main() 函數)中,我們嘗試兩次調用 pthread_join() 函數擷取 myThread 線程執行結束的傳回值。通過執行結果可以看到,第一個 pthread_join() 函數成功執行,而第二個 Pthread_join() 函數執行失敗。原因很簡單,第一個成功執行的 pthread_join() 函數會使 myThread 線程釋放自己占用的資源,myThread 線程也就不複存在,是以第二個 pthread_join() 函數會傳回 ESRCH。

繼續閱讀