2011-06-03 143 views
2

我的問題是與C中的線程編程有關。 我的問題是我只是想在我的主程序中創建兩個線程。這兩個線程應該順序工作,這意味着我的第一個線程應該首先執行(不應該執行任何線程的其他語句)。第一個線程應該完全控制。在第一個線程完成之前,不應該執行任何其他線程的其他語句,甚至是主程序語句。C語言和多線程編程

完成第一個線程後,應該以與第一個線程類似的方式執行第二個線程。

之後,我的主要執行。

我知道你可以說爲什麼我要這樣做,因爲這個事情可以通過創建兩個函數並按順序調用它來實現,但爲了學習和實驗,我希望在線程。

我寫一些C代碼如下:

void* fun() 
{ 
    printf("\nThe thread 1 is running"); 
} 
void* van() 
{ 
    printf("\nthread 2 is running "); 
} 

int main() 
{ 
    pthread_t t1,t2; 
    pthread_create(&t1,NULL,fun,NULL); 
    pthread_create(&t2,NULL,van,NULL); 
    printf("\nI'm in main\n"); 
    pthread_join(t2,NULL); 
} 

程序的工作完美,但我不理解的功能pthread_join()的工作。

當我改變我的代碼有點如下:

int main() 
{ 
    pthread_t t1,t2; 
    pthread_create(&t1,NULL,fun,NULL); 
    pthread_join(t2,NULL); // Change 
    pthread_create(&t2,NULL,van,NULL); 
    printf("\nI'm in main\n"); 
} 

現在,當我運行的代碼它顯示了一個分段錯誤。

現在我的問題有以下幾點:

  1. 中有什麼pthread_create()功能的屬性參數?我們爲什麼要使用它們?線程的默認屬性是什麼?請用一個例子來解釋。
  2. pthread_create()函數中的參數是什麼?我們爲什麼使用它們?線程的默認參數是什麼?請用一個例子來解釋。
  3. pthread_join()如何實際工作?當我的代碼主要使用pthread_join()作爲第一個參數t2時,這意味着什麼。這是否意味着main應該暫停執行,直到t2執行完成或其他什麼東西?
  4. pthread_join()中的第二個參數是什麼?我們爲什麼用它?它的默認值是多少?請用一個例子或代碼來解釋。
+1

你的線程函數應該返回一個值,即使它只是零,以便它們返回一個空的void指針。在「工作」代碼中,按照您的意圖進行排序純粹是巧合。兩個線程函數併發執行; 'main()'不會等待線程1在啓動線程2之前完成。如果等待線程1完成('pthread_join(&t1,NULL);'在其'pthread_create()'後面,那麼會最小化併發執行重複執行線程2.然後你可以在'main()'本身運行'printf()',因爲你已經等待每個線程完成了,你就完成了。 – 2011-06-03 05:49:37

回答

7
  1. 的ATTR參數指向一個pthread_attr_t結構,其內容在線程創建時被用來確定爲新的線程屬性;該結構使用pthread_attr_init(3)和相關功能進行初始化。如果attr爲NULL,則使用默認屬性(source)創建該線程。

  2. 將參數傳遞給您的線程函數。這是將數據傳遞給線程的最佳方式(與使用全局變量相反,例如)。

  3. 是的,pthread_join一直等到線程結束。這就是爲什麼當你在啓動線程之前調用pthread_join時程序失敗,因爲t2包含那個點的垃圾。

  4. 如果RETVAL不是NULL,則在pthread_join()拷貝目標線程的退出狀態(即,提供給了pthread_exit目標線程(3)的值)到位置由* RETVAL指向。如果目標線程被取消,則PTHREAD_CANCELED被放置在* retval中。 (source)。

即,你可以讓你的線程函數來通知你關於它的執行結果。

鑑於此,您的線程創建可能是這樣的:

struct th_arg{ 
    ... 
}; 

static void th_work(struct th_arg* a){ 
    //...some work 
    if (success) pthread_exit(EXIT_SUCCESS) 
    else pthread_exit(ERROR_CODE); 
} 

int main(){ 
    int t1,t2; 
    struct th_arg[2]; 
    int codes[2]; 
    // initialize th_arg2 
    pthread_create(&t1, NULL, th_work, th_arg+0, th_arg+0); 
    pthread_create(&t2, NULL, th_work, th_arg+1, th_arg+1); 
    pthread_join(t1, codes+0); 
    pthread_join(t2, codes+1); 

    if (codes[0] == EXIT_SUCCESS && codes[1] == EXIT_SUCCESS){ 
      ... 
    } 
} 
1
  • pthread_create屬性是pthread_attr_t類型。它保存有關線程的信息,包括線程內存地址開始的位置以及堆棧的大小等信息。大多數時候你不需要使用這個參數。

  • pthread_create中的arg被作爲唯一的參數傳遞給start_routine函數。這是一種黑客。由於指針可以指向任何東西(int,數組,結構體等),因此可以通過將指針傳遞給要傳入的所有數據來傳遞參數。大多數情況下,人們最終都會使用一個結構。線程沒有默認參數。如果你不想傳入任何東西,只需指定arg爲NULL。

作爲一個例子:

struct arguments 
{ 
    int something; 
    char* anotherArg; 
    short stillAnotherArg; 
} 

void* fun(void* arg) 
{ 
    struct arguments *my_args = (struct arguments*)arg; 
    printf("You said: %s\n", my_args->anotherArg); // Will print "You said: Hello there" 
    ... 
} 

int main() 
{ 
    pthread_t t1; 

    struct arguments my_args; 
    my_args.something = 5; 
    my_args.anotherArg = "Hello there"; 
    my_args.stillAnotherArg = 42; 

    pthread_create (&t1,NULL,fun, &my_args); 
    ... 
} 
  • pthread_join塊呼叫者直到指定線程完成。

  • pthread_join的第二個參數允許您在完成執行後捕獲線程的返回值。每個線程返回一個void*,第二個參數允許您指定返回值的存儲位置。

舉個例子:

void* fun(void* arg) 
{ 
    ... 
    return NULL; // not very exciting, but I don't want to get 
       // into memory management problems right now 
} 

int main() 
{ 
    ... 

    void* theReturnValue; 
    pthread_join(t2, &theReturnValue); 

    printf("fun returned %p\n", theReturnValue); // will print "fun returned 0x0" 
               // which is NULL 
} 

最後,它出現segfaults的原因是因爲你在等待的尚未定義的線程。