如何在使用pthread_create时传递参数

时间:2016-08-24 08:03:09

标签: c multithreading

我想创建三个线程并将一个整数传递给每个线程。我使用了pthread_create,我的代码如下。

#include<pthread.h>
#include<unistd.h>
#include<stdio.h>
#define NUM_OF_JOB 3

void* doJob(void* arg){
    int i = *((int*)arg);
    printf("%d\n",i);
}

void init_job() {
    pthread_t thread[NUM_OF_JOB];
    int index[NUM_OF_JOB]={-1,-1,-1};
    for(int i=0;i<NUM_OF_JOB;i++){
    pthread_create(&thread[i],NULL,doJob,(void*)(&index[i]));
    }
}

int main(){
    init_job();
    sleep(1);
    return 0;
}

我打算将-1传递给每个线程,但是在运行服务器代码的代码之后,我发现它没有打印三个-1。相反,他们可以产生奇怪的输出。那为什么呢?

可以找到类似的代码 pass arguments to the pthread_create function 我找不到他的代码和我的代码之间的任何不同。但是在他的代码中,线程可以获得预期的参数。

非常感谢你:)

顺便说一下,我尝试从上面的链接稍微更改代码,并运行它。令人惊讶的是,我的mordified版本也没有产生预期的结果。(我认为每个线程都应该得到自己的唯一整数作为参数) 这是我的mordified代码。任何人都可以解释一下吗?

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

#define THREAD_NUM 10

void *thread_func(void *arg)
{
    int v = *(int*)arg;

    printf("v = %d\n", v);

    return (void*)0;
}

int main(int argc, const char *argv[])
{
    pthread_t pids[THREAD_NUM];
    int rv;
    int i;

    for (i = 0; i < THREAD_NUM; i++) {
        rv = pthread_create(&pids[i], NULL, thread_func, (void*)(&i));
        if (rv != 0) {
           perror("failed to create child thread");
           return 1;
        }
    }
    for (i = 0; i < THREAD_NUM; i++) {
        pthread_join(pids[i], NULL);
    }
    return 0; 
}

再次感谢你:)

4 个答案:

答案 0 :(得分:5)

在第一个示例中,主线程从函数doJob返回,并且对象索引停止存在。然后线程尝试打印数组索引的值。由于对象索引不再存在,因此行为未定义。

如果你在从函数返回之前加入了线程,那么第一个例子是正确的。

第二个例子也是未定义的,因为存在数据竞争。变量i由多个线程读取并由主线程修改,没有任何同步。

要修复第二个示例,请使用整数数组,并将每个元素分别传递给创建的线程。

答案 1 :(得分:3)

第二个问题是因为所有线程都获得完全相同的指针。这样做的问题是您无法控制线程何时开始运行并复制该值。如果第一个线程没有立即启动并且创建线程的循环继续,它将增加变量,一旦线程启动它将看到错误的值。

第一个例子有另一个问题,但也与上述问题有关。问题是你将指针传递给超出范围的东西。一旦init_job返回,数组index将超出范围并且不再存在,如果没有线程已经开始运行,那么它们将取消引用的指针将不会指向您认为它们指向的内容。

答案 2 :(得分:1)

如前所述,问题是您的索引数组超出了线程上下文的范围。我想为您提供以下解决方案:

#include<pthread.h>
#include<unistd.h>
#include<stdio.h>
#define NUM_OF_JOB 3

int index[NUM_OF_JOB]={-1,-1,-1};

void* doJob(void* arg){
    int i = *((int*)arg);
    printf("%d\n",i);
}

void init_job() {
    pthread_t thread[NUM_OF_JOB];
    for(int i=0;i<NUM_OF_JOB;i++){
        pthread_create(&thread[i],NULL,doJob,&index[i]);
    }
}

int main(){
    init_job();
    sleep(1);
    return 0;
}

答案 3 :(得分:1)

您需要阻止调用线程,直到可以创建本地数据副本。信号量在这里很有用。

struct thread_param {
    void * args; sem_t * ready;
};

void * child(void * args)
{
    struct thread_param * param = args;
    /* make local copies. */
    sem_post(param->ready);
    /* do work. */
    return NULL;
}

int main(int argc, char * argv)
{
    /* setup (semaphore and other). */
    struct thread_param param;
    param.ready = &ready;

    for (i = 0; i < n; i++) {
        param.args = &i; /* or whatever. */
        pthread_create(&thread[i], &attrib, child, &param);
        sem_wait(param.ready);
    }
    /* cleanup, join on threads. */
    return 0;
}

注意:代码未经测试。我为任何错别字/错误道歉。