2012-06-04 63 views
4

這是我的代碼。這很簡單。Linux Pthread參數

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 

void *func(void *arg) 
{ 
    printf("ID=%d\n", *(int*)arg); 
    pthread_exit(NULL); 
} 

int main() 
{ 
    pthread_t pt[4]; 
    int i; 

    for (i = 0; i < 4; i++) 
    { 
     int temp = i; 
     pthread_create(&pt[i], NULL, func, (void*)&temp); 
    } 
    sleep(1); 
    return 0; 
} 

我編譯它:

gcc p_test.c -lpthread

我跑了。它印有2 2 3 3。我再次運行它。它印刷2 3 3 2

我的問題是:

爲什麼23印刷兩次?

爲什麼不打印1 3 2 0或其他結果?

+0

經典未定義行爲。一個普通的數據對象可能無法在一個線程中訪問,而另一個線程正在或可能正在修改它。 –

回答

7

這裏的主要問題是,你要取得局部變量temp的地址,然後在變量範圍之外使用該指針 - 只要退出循環的一次迭代,指向temp的指針就變爲無效,你不能解除引用。

3

您正將一個指向臨時變量的指針傳遞給線程創建函數,並且此臨時值超出了循環塊末尾的範圍。在我看來,編譯器正在重新使用臨時地址,因此當線程執行時,它們會看到相同的地址位置。

如果你這樣做:

int *temp = malloc(sizeof(int)); 
*temp = i; 
pthread_create(&pt[i], NULL, func, (void*)temp); 

相反,你應該可以看到你所期望的結果。

在這種情況下,線程函數在打印後需要釋放int以避免內存泄漏。

此外,最好練習pthread_join()您正在等待的線程,而不僅僅是sleep() ing。

+0

雖然確保你釋放你分配的內存(線程退出是一個好地方),以避免明顯的內存泄漏。 –

+0

@Philip肯德爾 - 是的!我剛剛意識到我應該指出這一點。 – TheJuice

+1

這是有效的,但將整數參數強制轉換爲'void *'會更有效率... –

0

因爲它打印temp,所有線程共享內存(爲什麼temp是「共享」由TheJuice解釋),所以所有線程都「共享」temp。使用mutex或使temp成爲一個私有變量。 Private Variables in Threads

或者您可以使用phtread_join這樣的:

int main() 
{ 
    pthread_t pt[4]; 
    int i; 

    for (i =0 ; i < 4; i++) 
    { 

     pthread_create(&pt[i], NULL, func, (void*)&i); 
     pthread_join(pt[i],NULL); 

    } 

    //sleep(1); 
    return 0; 
} 
+0

不完全:這個例子與'temp'超出範圍有很大不同。因此,在線程中解引用它的嘗試將引發未定義的行爲。 –

0
#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 

void *func(void* arg) 
{ 
printf("ID=%d\n", (int)arg); 
pthread_exit(NULL); 
return 0; 
} 

int main() 
{ 
pthread_t pt[4]; 
int i; 

for (i =0 ; i < 4; i++) 
{ 

    pthread_create(&pt[i], NULL, func, (void*)i); 
    pthread_join(pt[i],NULL); 
} 



return 0; 

}