我目前正在学习操作系统,我正在运行以下代码:
#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等我是多线程的初学者所以这个问题可能看起来很幼稚但我很感激有人能回答它。
答案 0 :(得分:4)
当线程正在运行时,您的线程正在处理指针到i
和i
更改值。
因此,您还有一个种族条件,您可以同时从不同的线程写入和读取相同的变量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
对于单个调用是线程安全的,但是当多个线程写入时,多个调用可以 interleaved 。因此,您的std::endl
可能不会恰好发生在每个输出数字之间(可能赢了),而且数字可能会出现在任何顺序中。
答案 1 :(得分:1)
这种情况正在发生,因为您从同一地址位置打印值,并且当生成的线程读取该值时,这是不可预测的。如果操作系统启动线程太快,您可能会看到值为0,1,2,3,但这不太可能。
答案 2 :(得分: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;
}