2010-09-11 413 views
23

以下程序顯示我們可以使用return()或pthread_exit()返回可用於pthread_join()狀態變量的void *變量。pthread啓動函數中的return()與pthread_exit()

(1)是否應該優先使用另一種?

(2)爲什麼使用return()工作?通常情況下,我們會考慮將返回值放在堆棧上,但由於線程完成,堆棧應該消失。或者在pthread_join()之後堆棧不會被銷燬?

(3)在你的工作中,你看到很多狀態變量的用法嗎?看來90%的代碼我只看到NULL狀態參數。由於任何通過void * ptr改變的東西已經在調用線程中反映出來,所以返回它似乎沒有多大意義。任何返回的新void * ptr都必須指向啓動線程malloc-ed,這使接收線程有責任處理它。我認爲狀態變量是半無意義的嗎?

#include <iostream> 
#include <pthread.h> 

using namespace std; 

struct taskdata 
{ 
     int x; 
    float y; 
    string z; 
}; 


void* task1(void *data) 
{ 
    taskdata *t = (taskdata *) data; 

    t->x += 25; 
    t->y -= 4.5; 
    t->z = "Goodbye"; 

    return(data); 
} 

void* task2(void *data) 
{ 
    taskdata *t = (taskdata *) data; 

    t->x -= 25; 
    t->y += 4.5; 
    t->z = "World"; 

    pthread_exit(data); 
} 


int main(int argc, char *argv[]) 
{ 
    pthread_t threadID; 

    taskdata t = {10, 10.0, "Hello"}; 

    void *status; 

    cout << "before " << t.x << " " << t.y << " " << t.z << endl; 

    //by return() 

    pthread_create(&threadID, NULL, task1, (void *) &t); 

    pthread_join(threadID, &status); 

    taskdata *ts = (taskdata *) status; 

    cout << "after task1 " << ts->x << " " << ts->y << " " << ts->z << endl; 

    //by pthread_exit() 

    pthread_create(&threadID, NULL, task2, (void *) &t); 

    pthread_join(threadID, &status); 

    ts = (taskdata *) status; 

    cout << "after task2 " << ts->x << " " << ts->y << " " << ts->z << endl; 

} 

隨着輸出:

before 10 10 Hello 
after task1 35 5.5 Goodbye 
after task2 10 10 World 

回答

30

(1)在C++代碼,用return導致堆棧是退繞和局部變量被破壞,而pthread_exit只保證調用取消處理程序與pthread_cancel_push()註冊。在某些系統上,這種機制也會導致C++局部變量的析構函數被調用,但這並不能保證可移植代碼---檢查你的平臺文檔。

此外,在main()return隱含的調用exit(),從而終止程序,而pthread_exit()只會終止線程,程序將繼續運行,直到所有線程終止或某個線程調用exit()abort()或其他功能終止程序。

(2)使用return的作品,因爲POSIX規範這麼說。返回的值存儲在pthread_join()可以檢索它的位置。在調用pthread_join()之前,線程使用的資源不會被回收。 (3)我從來不使用原始POSIX線程中線程的返回值。不過,我傾向於使用更高級別的工具,例如Boost線程庫,以及最近的C++ 0x線程庫,它們提供了在諸如期貨之類的線程之間傳遞值的替代方法,這避免了與內存管理相關的問題暗指。

+1

關於(1),pthread_exit不會立即終止線程,它首先運行取消處理程序。至少NPTL/g ++對取消處理程序和C++ dtors使用相同的機制,所以在這種情況下,pthread_exit確實可以展開堆棧。同樣,OpenVMS pthread_exit /線程取消展開堆棧並運行C++ dtors。您應該查看您的特定pthread實現的手冊,以瞭解pthread_exit和堆棧展開的行爲。 – 2010-09-11 21:05:58

+0

我已說明(1)將您的意見納入考慮範圍。 – 2010-09-11 21:33:15

+0

我絕對買你的書:)(希望它很快出來)。 – celavek 2011-03-22 08:23:21

6

我認爲return來自start_routine是可取的,因爲它確保了調用堆棧被正確解開。

對於C而言,這比C++更重要,因爲它沒有在初步退出後清理混亂的析構函數魔法。所以你的代碼應該通過調用堆棧上的例程的所有最後部分來執行free等。

爲什麼這個工程,這是簡單的

如果的start_routine返回時,效果應該好像有一個 隱含了pthread_exit()使用 的start_routine的返回值作爲退出狀態通話

對於我個人的經驗,我傾向於不使用終止線程的狀態很多。這就是爲什麼我經常有線程開始detached。但是這應該取決於應用程序,當然不是一般化的。