2014-04-20 40 views
2

我開始玩線程(pthreads),我不明白如何預測它們的工作方式。換句話說,我有這個非常簡單的程序,只是增加一個變量:使用線程的意外結果

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

int counter = 0; 

void *MyThread(void *arg) { 
    int i; 
    for (i = 0; i < 10000; i++) { 
     counter++; 
    } 

    return NULL; 
} 

int main() { 
    pthread_t tid[40]; 
    int i; 
    void *val; 
    void *MyThread(void *); 

    for (i = 0; i < 40; i++) { 
     pthread_create(&tid[i], NULL, MyThread, NULL); 
    } 

    for (i = 0; i < 40; i++) { 
     pthread_join(tid[i], &val); 
    } 

    printf("Counter = %d\n", counter); 
    return 0; 
} 

我不明白爲什麼它會給出隨機結果!如果我創建(並加入)40個線程,他們怎麼不會完成他們的工作?

+0

一個例子假定它打印出「反=「即所有線程都已完成 –

+0

您必須確保您不會同時在多個線程中更改'counter'。看看pthread_mutex_t。 – this

+0

併發訪問共享資源(這裏的全局變量「counter」)應該被保護/同步。 – alk

回答

2

增量不是原子操作。因此,如果每個線程同時訪問它,它很可能會破壞計數器值。如果您希望多個線程一次訪問變量,則只能使用原子操作或將操作包裝在互斥量或信號量中。

你可以做最簡單的修復,假設你正在使用gcc將與

__sync_fetch_and_add(&counter, 1); 

這取代了線

counter++; 

將取代使用原子增量遞增,並希望該程序將正確執行。

您可以找到有關原子操作在這裏更多的信息:http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html

1

他們都完成了自己的工作。但是,由於併發問題,它可能不會反映在counter中。
具體而言,在您的示例中沒有定義,或者根本沒有定義counter的更新,因爲您沒有同步它們。

1

您正在使用全局變量'counter'。該變量獨立遞增,而不是由您創建的所有線程同步。

你不能有一個共享變量(在你的情況 - 計數器)由多個線程同時處理適當的同步機制。否則,你將有一個race condition。這導致未定義的行爲。

您應該使用pthread互斥鎖來鎖定您的代碼,這些代碼不是原子的,並且可以改變共享變量,也可以由線程獨立執行。編寫多線程代碼時應注意thread safety