嗨,我有一个关于 pthreads 的问题
我反复测试 pthread_create 和 pthread_join,但似乎传递给函数的参数值没有正确传递
但是,如果我将 sleep() 代码放在 pthread_create 之后,效果很好
不知道为什么会这样,睡眠功能真的有必要吗?
代码:
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
void *thread_func(void *arg)
{
printf("I am thread #%d\n", *(int *)arg);
}
int main(int argc, char *argv[])
{
pthread_t t1[7];
while(1){
for(int i = 0; i < 7; i++){
pthread_create(&t1[i], NULL, &thread_func, &i);
}
sleep(10);
for(int j = 0; j < 7; j++){
pthread_join(t1[j], NULL);
}
sleep(10);
}
return 0;
}
int main(int argc, char *argv[])
{
pthread_t t1[7];
while(1){
for(int i = 0; i < 7; i++){
pthread_create(&t1[i], NULL, &thread_func, &i);
usleep(1);
}
sleep(10);
for(int j = 0; j < 7; j++){
pthread_join(t1[j], NULL);
}
sleep(10);
}
return 0;
}
我反复测试 pthread_create 和 pthread_join,但似乎传递给函数的参数值没有正确传递
半信半疑。
但是,如果我将 sleep() 代码放在 pthread_create 之后,效果很好
不知道为什么会这样,睡眠功能真的有必要吗?
调用
sleep()
是解决实际问题的方法。如果您的程序的未定义行为得到了令人满意的解决,那么无论是否调用 sleep()
,它都会产生想要的结果。
问题是,当您将
&i
作为最后一个参数传递给 pthread_create()
时,您会创建一种情况:原始线程和新线程都在查看同一个 int
对象,并且原始线程也在修改该对象在处理连续的循环迭代时。最终,循环范围内的对象的生命周期在循环终止时结束。由于线程之间没有合适的同步,因此程序的行为是未定义的。您的线程可以打印任何线程号,或者您的程序可能崩溃,或者原则上,计算机能力范围内的任何事情都可能发生。
可能的解决方案包括:
int
对象的指针。例如,
int args[7];
for (int i = 0; i < 7; i++){
args[i] = i;
pthread_create(&t1[i], NULL, &thread_func, &args[i]);
}
i
的值而不是指向 i
的指针:
for (int i = 0; i < 7; i++){
pthread_create(&t1[i], NULL, &thread_func, (void *) i);
}
然后线程函数需要将其适当地转换回来:
printf("I am thread #%d\n", (int) arg);
i
同时,当线程函数准备好让主线程继续运行时,它会增加信号量。也许是这样的:
sem_t startup_sem;
// ...
int main(int argc, char *argv[]) {
sem_init(&startup_sem, 0, 0);
// ...
for(int i = 0; i < 7; i++){
pthread_create(&t1[i], NULL, &thread_func, &i);
sem_wait(&startup_sem);
}
// ...