2017-09-16 67 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,但这不太可能。