所以我正在学习如何在C上使用线程,我写下了这段代码。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define number 3
void *funct(void *tid){
printf("Thread %d\n", *((int*)tid));
sleep(10);
printf("Thread %d finishes\n", *((int*)tid));
pthread_exit(NULL);
}
int main() {
pthread_t threads[number];
int i, status;
printf("Pid: %d\n", getpid());
for (i = 0; i < number; i++) {
printf("Thread number %d\n", i);
status = pthread_create(&threads[i], NULL, funct, (void*)&i);
if(status != 0){
printf("Error en la creación del hilo. La función devuelve %d\n", status);
exit(-1);
}
}
for (i = 0; i < number; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
我的问题是我想在funct
上用他们的号码识别它们,但有时输出是错误的。
Pid: 10142
Thread number 0
Thread number 1
Thread number 2
Thread 2
Thread 1
Thread 0
Thread 0 finishes
Thread 0 finishes
Thread 0 finishes
它不应该打印Thread 0 finishes
3次。我认为tid
的内容在线程调用之间发生了变化,这就是为什么它会打印另一个值。我该如何解决这个问题?
答案 0 :(得分:3)
您有一个data race,因为您将同一个变量i
的地址传递给所有线程函数。
您可以使用临时数组来传递线程&#34;数字&#34;。
int thr_id[number];
for (i = 0; i < number; i++) {
thr_id[i] = i;
printf("Thread number %d\n", i);
status = pthread_create(&threads[i], NULL, funct, &thr_id[i]);
...
另外,请注意C中无需使用无效指针。
答案 1 :(得分:1)
由于您将单个变量的变量传递给不同的线程,因此您有数据竞争,因此该变量的值将随着创建更多线程而更改。
在大多数/典型的实现中,您可以将整数转换为指针值本身,并且不再使用整数数组:
status = pthread_create(&threads[i], NULL, funct, (void *) (intptr_t) i);
然后在函数内部将接收的指针强制转换为整数:
printf("Thread %d\n", (int) (intptr_t) tid);
当intptr_t
的尺寸大于void *
的尺寸时,来自int
的演员应该有助于避免警告。例如,请参阅this question。