2017-09-16 70 views
1

目前我正在學習操作系統和我運行下面的代碼:簡單的C++並行線程程序的輸出不匹配預期

#include<iostream> 
#include<pthread.h> 
using namespace std; 
#define Num_Threads 4 

void *hello (void *arg){ 
    int* p = (int *)arg; 
    cout << *p << endl; 
    return 0; 
} 

int main(){ 
    int i = 0; 
    pthread_t tid[Num_Threads]; 
    for (i = 0; i < Num_Threads; i++){ 
     pthread_create(&tid[i], nullptr, hello, &i); 
    } 
    for (i = 0; i < Num_Threads; i++){ 
     pthread_join(tid[i], nullptr); 
    } 
    return 0; 
} 

我MAXOS使用下列編譯命令:

g++ pThead.cpp -pthread -o test 
./test 

我期待這個程序隨機輸出0,1,2,3的排列,但它通常有一些輸出,如3,0,0,0; 3,1,0,0等。我是初學者多線程,所以這個問題可能看起來很天真,但我很感激,如果有人能回答它。

+3

是否有一個原因,你不能使用'C++ 11'和新標準''頭? – Galik

回答

0

您的線程運行得太快。可能輸出一個數字只需要幾十微秒,並且你的系統不會安排或運行速度很快的線程。

嘗試運行一些日常比你hello

我期待這個節目的0隨機輸出排列,1,2,3

「隨機」是不正確的更復雜字。你的意思是 「不可預測」

 pthread_create(&tid[i], nullptr, hello, &i); 

&i是錯誤的:所有的線程得到相同的地址。

無論是分配上的堆:

 int *p = malloc(sizeof(int)); 
     if (!p) { perror("malloc"); exit(EXIT_FAILURE); }; 
     *p = i; 
     pthread_create(&tid[i], nullptr, hello, p); 

但你有內存泄漏(因爲你永遠不free

或直接傳遞整數(因爲int適合在一個詞上大多數平臺)

 pthread_create(&tid[i], nullptr, hellodirect, (void*)(intptr_t)i); 

但您需要另一個功能

void *hellodirect (void *arg){ 
    int i = (int)(intptr_t)arg; 
    cout << i << endl; 
    return nullptr; 
} 
+0

另請注意,寫入'cout'是序列化的。 –

+0

我不這麼認爲(一般) –

4

您的線程正在處理指針ii在線程運行時更改了值。

因此,您還有一個比賽您正在寫入並從同一個變量i同時從不同線程讀取的條件。

一個可能的解決方案是爲每個線程創建一個具有獨立變量的數組。

#include<iostream> 
#include<pthread.h> 
using namespace std; 
#define Num_Threads 4 

void *hello (void *arg){ 
    int* p = (int *)arg; 
    cout << *p << endl; 
    return 0; 
} 

int main(){ 

    pthread_t tid[Num_Threads]; 

    int v[Num_Threads]; // a variable for each thread 

    for (int i = 0; i < Num_Threads; i++){ 

     v[i] = i; // set a variable unique to each thread 
     pthread_create(&tid[i], nullptr, hello, &v[i]); 
    } 

    for (int i = 0; i < Num_Threads; i++){ 
     pthread_join(tid[i], nullptr); 
    } 
    return 0; 
} 

當然std::cout的是對單個呼叫線程安全但多個電話可以得到交錯當多個線程在寫它。所以你的std::endl可能不會發生在每個輸出數字之間(可能不會),並且數字可能發生在任何的順序。

+0

是的,我明白了!非常感謝! – LAWRENCE

1

發生這種情況是因爲您要從相同的地址位置打印值,並且生成的線程讀取的值不可預知。如果操作系統啓動線程太快,您可能會看到值爲0,1,2,3,但這不太可能。