简体   繁体   English

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

[英]In C, how do I pass variables to functions in Pthreads upon thread creation?

Working from this example: 从这个例子开始:

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

I've worked backwards and tried to edit in what I'm hoping to accomplish. 我已经倒退了,并尝试编辑我希望完成的任务。 I'd like to pass data to the thread being spawned. 我想将数据传递给正在生成的线程。

#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);
}

I see on line: 我在网上看到:

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

My function Entropy gets called here, so I thought I'd try to tack on some brackets and pass a variable to that function the way I'd seen it done before. 我的函数Entropy在这里被调用,所以我想我会尝试使用一些括号并将变量传递给该函数,就像我之前看到的那样。 This seems to be a little different though, since this whole line returns something to rc, I wonder if that changes how I pass data to my thread, but I'm not sure how else I'd do it. 这似乎有点不同,因为整行返回rc的东西,我想知道这是否会改变我将数据传递给我的线程的方式,但我不确定我是怎么做的。

Right now this code compiles and runs, int main() goes fine without a hitch but it seg faults the moment it tries to create new threads. 现在这个代码编译并运行,int main()顺利进行,但它在尝试创建新线程时会出错。

In order to pass data to a thread you need to prepare the data in some place in memory, and pass a pointer to that place into pthread_create . 为了将数据传递给线程,您需要在内存中的某个位置准备数据,并将指向该位置的指针传递给pthread_create It is pthread_create 's job to pass that pointer to the runner function of your thread: 将指针传递给线程的runner函数是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]);
}

Your code crashes since you pass incorrect parameters: 您传递的错误参数导致代码崩溃:

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

Here you should pass function pointer void *(*)(void *) but you are passing void * , and moreover value is unspecified since Entropy() has no return statement (did you turn warnings on at all?). 在这里你应该传递函数指针void *(*)(void *)但是你传递的是void * ,而且值是未指定的,因为Entropy()没有return语句(你根本没有打开警告吗?)。 I guess it should be like this: 我想它应该是这样的:

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

Next, how to pass parameter to thread routine? 接下来,如何将参数传递给线程例程? Technically you can use any pointer, but you should think twice about what you are passing. 从技术上讲,你可以使用任何指针,但你应该三思而后行。 First of all pointed data must be valid when new thread runs. 首先,当新线程运行时,指向的数据必须有效。 Ie you shouldn't pass addresses of any locals except if you are sure that thread is finished when you are leaving scope of passed data - use pthread_join(new_thread) at the scope end to achieve that. 即你不应该传递任何本地的地址,除非你确定当你离开传递数据的范围时线程已经完成 - 在范围结束时使用pthread_join(new_thread)来实现这一点。 Another approach is to pass pointer to data at global scope, that is surely valid at any moment. 另一种方法是将指针传递给全局范围内的数据,这在任何时候都是肯定有效的。 But there is one flaw - such data are visible to all threads, so you may accidentally make a mess. 但是有一个缺陷 - 所有线程都可以看到这样的数据,因此您可能会意外地弄乱。 To avoid it - use dynamic memory - allocate data block with malloc() pass pointer to thread and free it in that thread. 为了避免它 - 使用动态内存 - 使用malloc()传递指针分配数据块到线程并在该线程中释放它。 Latter option reduces chances to corrupt someone's else data. 后期选项减少了破坏某人其他人数据的机会。

#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);
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM