这是我的代码。这很简单。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *func(void *arg)
{
printf("ID=%dn", *(int*)arg);
pthread_exit(NULL);
}
int main()
{
pthread_t pt[4];
int i;
for (i = 0; i < 4; i++)
{
int temp = i;
pthread_create(&pt[i], NULL, func, (void*)&temp);
}
sleep(1);
return 0;
}
我编译了它:
gcc p_test.c -lpthread
我运行了它。它打印了2 2 3 3
.我又跑了一遍。它印了2 3 3 2
.
我的问题是:
为什么2
或3
打印两次?
为什么它没有打印1 3 2 0
或任何其他结果?
这里的主要问题是你获取局部变量的地址temp
,然后在变量范围之外使用该指针 - 一旦你退出循环的一次迭代,你指向temp
的指针就会变得无效,你不能取消引用它。
您将指向临时变量的指针传递到线程创建函数中,并且此临时变量在循环块末尾超出了范围。 在我看来,编译器正在重用临时地址,因此当线程执行时,它们会看到相同的地址位置。
如果您这样做:
int *temp = malloc(sizeof(int));
*temp = i;
pthread_create(&pt[i], NULL, func, (void*)temp);
相反,您应该看到预期的结果。
在这种情况下,thread函数需要在打印后释放int
,以避免内存泄漏。
此外,更好的做法是pthread_join()
您正在等待的线程,而不仅仅是sleep()
。
因为它打印temp,所以所有线程共享内存(为什么temp是"共享"由TheJuice解释),所以所有线程"共享"temp。使用互斥锁或将 temp 设为私有变量。线程中的私有变量
或者你可以像这样使用phtread_join:
int main()
{
pthread_t pt[4];
int i;
for (i =0 ; i < 4; i++)
{
pthread_create(&pt[i], NULL, func, (void*)&i);
pthread_join(pt[i],NULL);
}
//sleep(1);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *func(void* arg)
{
printf("ID=%dn", (int)arg);
pthread_exit(NULL);
return 0;
}
int main()
{
pthread_t pt[4];
int i;
for (i =0 ; i < 4; i++)
{
pthread_create(&pt[i], NULL, func, (void*)i);
pthread_join(pt[i],NULL);
}
return 0;
}