在C中,如何在创建线程时将变量传递给Pthreads中的函数?

时间:2016-08-17 13:00:01

标签: c function variables pthreads

从这个例子开始:

https://computing.llnl.gov/tutorials/pthreads/samples/hello.c

我已经倒退了,并尝试编辑我希望完成的事情。 我想将数据传递给正在生成的线程。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
long NUM_THREADS=0;

void *Entropy(void *depth)
{
   long tid;
   tid = (long)depth;
   printf("This is where things get done.\n", tid);
   pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
   NUM_THREADS = sysconf(_SC_NPROCESSORS_ONLN);
   printf("Cores: %i\n", NUM_THREADS);
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   int depth;
   depth = atoi(argv[1]);
   for(t=0;t<NUM_THREADS;t++){
     printf("In main: creating thread %ld\n", t);
     rc = pthread_create(&threads[t], NULL, Entropy(depth), (void *)t);
     if (rc){
       printf("ERROR; return code from pthread_create() is %d\n", rc);
       exit(-1);
       }
     }
   pthread_exit(NULL);
}

我在网上看到了:

rc = pthread_create(&threads[t], NULL, Entropy(depth), (void *)t);

我的函数Entropy在这里被调用,所以我想我会尝试使用某些括号并将变量传递给该函数,就像我之前看到的那样。这似乎有点不同,因为整行都返回了rc,我想知道这是否会改变我将数据传递给我的线程的方式,但我不确定我是怎么做的。< / p>

现在这段代码编译并运行,int main()顺利进行,但是当它尝试创建新线程时它会出错。

2 个答案:

答案 0 :(得分:2)

为了将数据传递给线程,您需要在内存中的某个位置准备数据,并将指向该位置的指针传递到pthread_create。将该指针传递给线程的转轮函数是pthread_create的工作:

typedef struct {
    long tid;
    int depth;
}thread_data;
...
void *Entropy(void *dataPtr) {
   thread_data *data= (thread_data*)dataPtr;
   printf("This is where things get done for %li.\n", data->tid);
   pthread_exit(NULL);
}
...
pthread_t threads[NUM_THREADS];
thread_data data[NUM_THREADS];
...
for(t=0;t<NUM_THREADS;t++) {
    data[t].tid = t;
    data[t].depth = depth;
    rc = pthread_create(&threads[t], NULL, Entropy, (void *)&data[t]);
}

答案 1 :(得分:1)

您传递的错误参数导致代码崩溃:

rc = pthread_create(&threads[t], NULL, Entropy(depth), (void *)t);
                                    // ^^^^^^^^^^^^^^

在这里你应该传递函数指针void *(*)(void *),但是你传递的是void *,而且由于Entropy()没有返回语句(你根本没有打开警告吗?),因此未指定值。我想它应该是这样的:

rc = pthread_create(&threads[t], NULL, Entropy, (void *)t);

接下来,如何将参数传递给线程例程?从技术上讲,你可以使用任何指针,但你应该三思而后行。首先,当新线程运行时,指向的数据必须有效。即你不应该传递任何本地的地址,除非你确定在离开传递数据的范围时完成了线程 - 在范围结束时使用pthread_join(new_thread)来实现这一点。另一种方法是将指针传递给全局范围内的数据,这在任何时候都是肯定有效的。但是有一个缺陷 - 所有线程都可以看到这样的数据,因此您可能会意外地弄乱。为了避免它 - 使用动态内存 - 使用malloc()传递指针将数据块分配给线程并在该线程中释放它。后期选项减少了破坏某人其他人数据的机会。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
long NUM_THREADS=0;

void *Entropy(void *depth)
{
   long tid = *((long *)depth);
   free(depth);
   printf("This is where things get done.\n", tid);
   return NULL;
}

int main(int argc, char *argv[])
{
   NUM_THREADS = sysconf(_SC_NPROCESSORS_ONLN);
   printf("Cores: %i\n", NUM_THREADS);
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   int depth;
   depth = atoi(argv[1]);
   for(t=0;t<NUM_THREADS;t++){
     long *arg = malloc(sizeof(*arg));
     *arg = t;
     printf("In main: creating thread %ld\n", t);
     rc = pthread_create(&threads[t], NULL, Entropy, arg);
     if (rc){
       printf("ERROR; return code from pthread_create() is %d\n", rc);
       exit(-1);
       }
   }
   for(t=0;t<NUM_THREADS;t++){
     pthread_join(threads[t], NULL);
   }
}