正确使用方法一:ptread_create()中传递值//使用值传递,而不是指针传递。
typdedef struct{
char ch*;
int aa;
}STR;
void* func(void * arg)
{
int b = (int)arg;
printf("%d",b);
STR* str = (STR*)malloc(sizeof(STR));
str->ch="hello";
str->aa = 100;
pthread_exit((void*)str);
}
main()
{
pthread_t tid[2];
for(i=0;i<2;i++)
pthread_create(&tid[i],NULL,ftn,(void *)i);//值传递,因为参数为地址,故强转成地址
for(i=0;i<n;i++) //回收每个子线程
{
STR *re; //re位于主控线程的栈空间,但是re本身的值为子线程传给它的值。
pthread_join( tid[i],(void **)&re);
}
}
注意问题:
1、如下图所示,此处是(void*)i,而不是(void*)&i,因为线程创建的时候,不能传递一个变化的参数,此处,i由0变成1。
2、如下图所示,1条中传递的值,线程函数中转换的时候,直接转int,转换是与phtread_create的保持一致。取的是这个地址值i.
3、 如下图所示,传递的参数和返回的参数并不是同一个
4、 如下图所示,因为返回值是指针,所以函数中的指针需是动态创建的。
正确使用方法二:ptread_create()中使用动态指针传递
//下例中,free与malloc不在同一函数中,这一点可以继续优化。
void* func(void* arg)
{
int value = *(int*)arg;
free(arg);//------------------->在参数使用结束后,对malloc的内存释放。
printf("%d\n",value);
}
int main(void)
{
pthread_t pid[6];
int ret;
for (int i=0; i<6; ++i)
{
int *p = malloc(sizeof(*p));
if(p==NULL)
{
perror("malloc");
exit(1);
}
*p = i;
if ((ret=pthread_create(&pid[i],NULL,thread,(void*)p)) != 0)
{
fprintf(stderr,"pthread_create:%s\n",strerror(ret));
exit(1);
}
}
for(int j=0;j<6;j++)
{
pthread_join(pid[i],NULL);
}
}
//利用pthread_exit()函数的返回值将free与malloc放在同一函数中
void* func(void* arg)
{
int value = *(int*)arg;
//free(arg);//------------------->在参数使用结束后,对malloc的内存释放。
printf("%d\n",value);
pthread_exit(arg);
}
int main(void)
{
pthread_t pid[6];
int ret;
void *ptr;
for (int i=0; i<6; ++i)
{
int *p = malloc(sizeof(*p));
if(p==NULL)
{
perror("malloc");
exit(1);
}
*p = i;
if ((ret=pthread_create(&pid[i],NULL,thread,(void*)p)) != 0)
{
fprintf(stderr,"pthread_create:%s\n",strerror(ret));
exit(1);
}
}
for(int j=0;j<6;j++)
{
pthread_join(pid[i],&ptr);//-----------收到线程传过来的参数。
free(ptr);//-----------------释放内存
}
exit(0);
}
1、如下图所示,用动态指针传递,也不会发生问题
错误方法三:错误示范,参数传递指针
//多个线程之间存在竞争,线程函数中 int value = *(int*)arg; 多个arg指针都指向了同一片内存,上述两种方法不存在竞争的原因是,一个指针指向一个变量。
void* func(void* arg)
{
int value = *(int*)arg;
printf("%d\n",value);
}
int main(void)
{
pthread_t pid[6];
int ret;
for (int i=0; i<6; ++i)
{
if ((ret=pthread_create(&pid[i],NULL,thread,(void*)&i)) != 0)
{
fprintf(stderr,"pthread_create:%s\n",strerror(ret));
exit(1);
}
}
}
输出结果:
2
3
6
6
6
6
1、如下图所示,正常的思维是,传递i的地址,但是运行会出现错误,原因是线程的创建需要时间,
for循环中,执行了6个phread_create()函数后,i变为了6,因为线程中调用thread函数时需要一定的时间,此时再去到&i地址去取i值时,i都变为6了,所以会出现上述的情况。
所以,情况一和情况二的可以避免这种情况的发生。
总结: 不能在线程创建过程中,改变传递的参数,避免该问题产生的方法是传递值或者使用动态申请内存的方法。