2017-02-16 109 views
0

這是我寫的一個簡單的程序。它創造了一個10個線程的循環和每個線程打印i的值:Pthread沒有打印正確的值

#include <stdio.h> 
#include <pthread.h> 
void* basic_function(void *num){ 
    int cur_num = *(int*)num; 
    printf("Current thread number is :%d\n", cur_num); 
    return NULL; 
} 

int main(int argc, const char * argv[]) { 
    pthread_t thread_id [10]; 
    void * exit_status[10]; 

    for (int i = 0; i < 10; i++){ 
     pthread_create(&thread_id[i], NULL, basic_function, &i); 
     printf("i is: %d\n", i); 
    } 


    for (int i = 0; i<10; i++){ 
     pthread_join(thread_id[i], &exit_status[i]); 


    return 0; 
} 

我想輸出應該看起來像一些打印語句從0到9,以正確的順序:

Current thread number is: 0 
i is: 0 
Current thread number is: 1 
i is: 1 
Current thread number is: 2 
i is: 2 
... 

而是我的輸出是:

i is: 0 
i is: 1 
i is: 2 
i is: 3 
i is: 4 
i is: 5 
Current thread number is: 6 
Current thread number is: 6 
i is: 6 
Current thread number is: 6 
Current thread number is: 6 
Current thread number is: 6 
Current thread number is: 6 
Current thread number is: 6 
i is: 7 
Current thread number is: 7 
i is: 8 
Current thread number is: 9 
Current thread number is: 9 
i is: 9 

爲什麼用線6創造了多次?爲什麼有些線程沒有創建?還有,爲什麼我運行程序時總會得到不同的輸出結果?

回答

1

因爲傳遞給線程函數的參數指向相同的變量 - i

而作爲變量i不斷從main功能更新,螺紋總是在其運行的時間得到最新的值與線程做,在與main方法並行。此外,一旦循環已經完成,可能會發生線程訪問變量,在這種情況下,它是未定義的行爲。

解決方法是在堆上分配i的副本並將指針傳遞給副本。或者另一個更髒的解決方案是將i轉換爲指針,作爲參數傳遞,然後在線程中轉換回int。這依賴於int小於指針,這是相當普遍的,但在一些模糊的架構可能不是真實的(可能不是這樣的小數字)。

+0

我明白你的第一個解決方案。但我不知道爲什麼將'i'指向指針可以解決問題。我認爲它與'pthread_create(&thread_id [i],NULL,basic_function,&i)'有相同的效果,這是我在我的文章中所做的。 – HalfOfRain

+0

不,它沒有相同的效果,因爲投射到指針會創建指針所攜帶的整數的副本。不像Zbynek指出的那樣便攜,但如果可行的話可靠 – LWimsey