使用唯一结构作为参数C的pthread

时间:2010-04-05 01:45:12

标签: c parameters struct pthreads

我有这段代码给我带来麻烦。 我知道所有线程都在读取相同的结构。但我不知道如何解决这个问题。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct {
  int a,b;
} s_param;

void *
threadfunc(void *parm)
{
  s_param *param2 = parm; 
  printf("ID:%d and v:%d\n",param2->a,param2->b);
  pthread_exit(NULL);
}

int main(int argc, char **argv)
{
  pthread_t thread[3];
  int rc=0,i;
  void * status;

  for(i=0; i<3 ; ++i){
    s_param param;
    param.b=10;
    param.a=i;
    rc = pthread_create(&thread[i], NULL, threadfunc, &param ); // !!!!
    if(rc){
      exit(1);
    }
  }  

  for(i=0; i<3 ; ++i){
    pthread_join(thread[i],&status);
  }
  return 0;
}

输出:

ID:2 and v:10
ID:2 and v:10
ID:2 and v:10

以及我需要的东西:

ID:0 and v:10
ID:1 and v:10
ID:2 and v:10

3 个答案:

答案 0 :(得分:5)

for循环中的sparam的范围在该循环中是静态的。当你设置.a和.b时,你反复写入相同的结构,并且所有三个线程都获得指向同一个结构的指针。

相反,您可以通过创建它们的数组来创建结构的三个单独实例。

int main(int argc, char **argv)
{
  pthread_t thread[3];
  s_param param[3];
  int rc=0,i;
  void * status;

  for(i=0; i<3 ; ++i){
    param[i].b=10;
    param[i].a=i;
    rc = pthread_create(&thread[i], NULL, threadfunc, &param[i] ); // !!!!
    if(rc){
      exit(1);
    }
  } 
... etc

应该提到在这样的数组中创建结构(和线程)是可行的,因为你明确地用主线程做了一个join()。如果你没有这样做,你会被建议静态地在主函数之外分配结构,或者从堆中malloc它们,因为一旦入口线程退出main函数,包含数组的堆栈框架将变为无效,并将很快以不可预测的方式被覆盖。

答案 1 :(得分:2)

在执行param函数期间,

main位于堆栈中的同一位置。每次设置新值时,它们都会消除旧值,并且所有threadfunc s都在查看内存中的相同位置。 malloc结构,或以其他方式从不同的内存位置创建它们。 (另外,使用堆栈内存用于跨线程数据结构是令人担忧的;只要你在退出时设置它们的功能,内存就无效。)

答案 2 :(得分:2)

param是一个局部变量。它在循环结束时超出了范围。每个帖子都需要malloc一个新的s_param

或者更好的是,定义一个同时包含pthread_ts_param的结构,并将该类型用于thread[3]

typedef struct {
  int a,b;
  pthread_t t;
} s_param;

int main(int argc, char **argv)
{
  s_param thread[3]; // declare threads + params together
  int rc=0,i;
  void * status;

  for(i=0; i<3 ; ++i){
    s_param *param = &thread[i]; // no persistent data declared here
    param->b=10;
    param->a=i;
    rc = pthread_create(&thread[i].t, NULL, threadfunc, &thread[i] ); // !!!!
    if(rc){
      exit(1);
    }
  }  
…