多线程调用同一函数并传递多参数

多线程调用同一函数并传递多参数,例子如下:
多线程运行时,是随机的,不是按顺序执行的,这点要明白
主线程伪代码:
int i;
pthread_t record_thread[4];
thread_save_s *save_s[4];
//thread_save_s save_s[4];//我们都知道当传递多参数的时候就用结构体,如果定义成结构体变量,就不用去分配内存和释放内存了,
但是传递参数必须要用指针,如果用变量,这个函数结束,它就释放了

for(i=0;i<4;i++)
{
save_s[i] = (thread_save_s *)malloc(sizeof(thread_save_s));//既然定义的是结构体指针,要想往里面存数据,当然要分配内存
memset(save_s[i], 0, sizeof(thread_save_s));
strcpy(save_s[i]->pdata, "123");
save_s[i]->datalen = 3;
save_s[i]->type = i;
save_s[i]->index_freq = i;
save_s[i]->serviceid = i;

pthread_create(&record_thread[i], NULL, (void *)data_save_file, save_s[i]);
//pthread_detach(record_thread[i]);
//free(save_s[i]);//如果在主线程里释放,很有可能子线程还没有得到这些数据,它们就被清空了
}

for(i=0; i<4; i++)
pthread_join(record_thread[i], NULL);//当是多线程的时候,应该用pthread_join,不要用pthread_detach,将这放在程序最后,应该就不会阻塞了
子线程伪代码:
void data_save_file(void* arg)//保存数据到文件
{
thread_save_s *save_s = (thread_save_s *)arg;
……
free(save_s);//正确的是应该在子线程里释放
}
还需要注意的是,在线程函数里,应尽量多避免使用栈空间,否则很容易引起栈溢出。比如写文件,要用write,而不要用fwrite,
因为fwrite会申请缓存,占用栈空间(在fclose之前加了个fflush,奇迹般的没有问题了)
举一反三:
这种用结构体封装多参数的用法不仅仅用在pthread_create函数中,如果你自己设计的函数需要的参数很多〉=5个以上,
都可以考虑使用结构体封装,这样对外你的接口很简洁清晰,你的函数的消费者使用起来也很方便,只需要对结构体各个成员赋值即可,
避免了参数很多时漏传、误传(参数串位)的问题
线程传递参数问题:当我们传递给线程的参数是全局的时候,比如说一个全局的结构体,在子线程里我们会发现,得到这些参数的值可能不对,
难道传参数都会传错,当然不是。那是因为,我们在主线程的某些地方也使用了这个全局结构体,并修改了里面成员的值,
所以导致了子线程里的参数内容变了。所以当传递给线程的参数是全局,并会在多处地方使用的时候,我们必须要专门定义一个局部指针变量,
并且为它分配内存空间,将当前该参数内容赋给这个局部指针变量,然后传递时就传递这个局部指针变量,这样一来,
不管以后这个全局参数怎么变,子线程里的参数内容都不会受影响了。
那为什么用函数

传递全局结构体时,就不会出现这种问题呢?那是因为函数是顺序执行的,这个函数没有执行完,就不会往下执行,
所以后面的程序不会影响到当前参数的值;而线程不一样,它是并行执行的,可能在传递当前参数值的过程中,后面的程序就将参数值内容给改了,
导致了在子线程里得到的参数内容不对;所以线程并行执行的好处是,解决了程序中阻塞的问题,但同时也带来了并行执行时相互影响的问题。
示例程序:
主线程伪代码:
fileupdateset_cmd* fileupdateset_cmdinfo=NULL;
fileupdateset_cmd* fileupdateset_thread=(fileupdateset_cmd*)malloc(fileupdateset_len);//专门定义一个结构体指针变量,并分配存储空间
fileupdateset_cmdinfo = pMsg->msg_info.protocol_info;

strcpy((char*)fileupdateset_thread->FtpIp, (char*)fileupdateset_cmdinfo->FtpIp);//将当前参数值赋给这个结构体指针变量
strcpy((char*)fileupdateset_thread->FtpPwd, (char*)fileupdateset_cmdinfo->FtpPwd);
strcpy((char*)fileupdateset_thread->FtpUserName, (char*)fileupdateset_cmdinfo->FtpUserName);

printf("ip=%s\n", fileupdateset_cmdinfo->FtpIp);//打印出传递前参数的值
pthread_t thread_update;
pthread_create(&thread_update, NULL, (void*)FileUpdate_run, fileupdateset_thread);//传递时用这个结构体指针变量
//while(1);//用while(1)在这里阻塞住,不往后执行,程序结果也是对的,很显然说明了后面的程序改变了当前参数的内容
pthread_detach(thread_update);
//FileUpdate_run(fileupdateset_cmdinfo);//用函数传递就不会出现问题
子线程伪代码:
static void FileUpdate_run(void* arg)
{
fileupdateset_cmd* info=(fileupdateset_cmd *)arg;
printf("name=%s, pwd=%s, ip=%s\n", info->FtpUserName, info->FtpPwd, info->FtpIp);//打印出子线程里接收到的参数值
……
}
注意:所以在以后给线程传参时,应尽量用局部变量

相关文档
最新文档