2016-08-24 145 views
1

我想创建三个线程并将一个整数传递给每个线程。我用pthread_create,我的代码如下。如何在使用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 我找不到他的代码和我的代码有什么不同。但是在他的代码中,线程可以得到预期的参数。

非常感谢你:)

顺便说一句,我试图改变从上面的链接一点点的代码,it.surprisingly跑,我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; 
} 

再次谢谢:)

回答

5

在第一个例子,从功能doJob主线程返回,对象指数停止现有的。然后线程尝试打印数组索引的值。由于对象索引不再存在,因此行为未定义。

如果您在从函数返回之前加入线程,第一个示例将是正确的。

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

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

+0

第二个问题与第一个不同,变量'i'不会超出范围。 –

+0

@JoachimPileborg谢谢。 – 2501

+0

谢谢,但在原始链接中,代码如下: 'pthread_create(&pids [i],NULL,thread_func,(void *)(i));' 并在** thread_func **中,它使用int ** v =(int)arg **,结果是正确的。为什么没有数据竞赛? 此外,该代码使用gcc编译,但使用g ++,不允许从void *转换为int,因此如何将这段代码与我的cpp代码整合在一起? :) – Casualet

3

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

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

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; 
} 
+0

调用sleep()并不是一个好主意。相反,在一个循环中,为每个线程调用'pthread_join()'(全局保存线程ID,这样它们将可用于调用'pthread_join()' – user3629249

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

注:代码是未经测试。我对任何错误/错误表示歉意。

相关问题