2016-11-02 39 views
1

我試着編寫一個帶有2個線程的代碼,它應該將2個數字y增加到100,每次發生增量時,都應該打印出來。使用多線程遞增變量的值

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

void *inc_x(void *x_void_ptr){ 
    int *x_ptr = (int *)x_void_ptr; 
    while (++(*x_ptr)<100) { 
     printf("x increment to %d \n",*x_ptr); 
     *x_ptr++; 
    } 
    return NULL; 

} 

void *inc_y(void *y_void_ptr){ 
    int *y_ptr = (int *)y_void_ptr; 
    while (++(*y_ptr)<100) { 
     printf("y increment to %d \n",*y_ptr); 
     *y_ptr++; 
    } 
    return NULL; 
} 

int main() 
{ 
    int x = 0; 
    int y = 0; 
    printf("x: 0 , y : 0\n"); 
    pthread_t inc_x_thread, inc_y_thread; 
    if (pthread_create(&inc_x_thread, NULL, inc_x, &x)) { 
     fprintf(stderr, "Error creating thread \n"); 
     return 1; 
    } 
    if (pthread_create(&inc_y_thread, NULL, inc_y, &y)) { 
     fprintf(stderr, "Error creating thread \n"); 
     return 2; 
    } 
    printf("%d , %d" , x,y); 

    return 0; 
} 

但我的x,y值沒有增加。有人能告訴我爲什麼嗎?謝謝(順便說一句,我是C新手)。

+6

'* x_ptr ++;'增加指針。你也不要等待線程。 – mch

+3

你怎麼知道他們不增加?它是一個多線程程序,你不能知道'mainf中的printf(「%d,%d」,x,y);'會在線程之前還是之後執行。 – Lundin

+0

如果你修復指針增量(見mch)。你在一次循環迭代中增加值兩次 –

回答

5

沒有同步發生。特別是,你沒有pthread_join()的線程。

這意味着什麼意思是說,當你試圖打印出結果時,線程甚至都沒有運行。他們可能跑了,但你無法確定。

此外,請參閱上面的@mch評論:您確實沒有遞增計數器,以添加到以前。所以即使線程確實運行了,結果也不會是你想要的。

對於正確的操作,一般來說,您應該發出一個條件變量(並在消耗線程上等待)以確保結果已準備好,或者在訪問結果之前連接線程。發信號通知一個條件變量的重量較輕,所以這就是你想要做的重複任務,而不是產卵/連接數千個線程。 (在某些情況下,可以在線程之間成功地共享數據,使用原子操作,但對於初學者來說,線程過於先進,太容易讓你的生活相當不高興,因此現在就使用cond vars。 )

您通常會希望確保沒有「遺忘」的線程仍在運行時程序退出,這是另一個很好的理由罵pthread_join,即使你是不是在同步太大的興趣,否則。

您可能會傾向於認爲它並不重要,因爲程序退出,有時甚至是這樣。但總的來說,這個假設是無效的。你可以例如非常好的文件被寫入或半寫入文件,因爲線程在操作中突然中斷。
或者你可能有一個工作線程段錯誤,而操作系統突然拉開它仍然從腳下訪問的內存頁面。其中「看起來」完全正常,除非沒有。

+0

另外,主函數應該調用'pthread_exit()' – Aif

1

使用在主以下之前檢查x和y的反射值:

pthread_join(inc_x_thread, NULL); 
    pthread_join(inc_y_thread, NULL); 

和在兩種功能

使用像這樣同時增加:(* y_ptr)++;

void *inc_y(void *y_void_ptr){ 
    int *y_ptr = (int *)y_void_ptr; 
    while (++(*y_ptr)<100) { 
    printf("y increment to %d \n",*y_ptr); 
    (*y_ptr)++; // correction here 
    } 
    return NULL; 
    }