pthread_create()参数传递注意问题(参数传地址问题)

 正确使用方法一: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了,所以会出现上述的情况。

所以,情况一和情况二的可以避免这种情况的发生。

总结: 不能在线程创建过程中,改变传递的参数,避免该问题产生的方法是传递值或者使用动态申请内存的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值