我想创建三个线程并将一个整数传递给每个线程。我使用了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;
}
再次感谢你:)
答案 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, ¶m);
sem_wait(param.ready);
}
/* cleanup, join on threads. */
return 0;
}
注意:代码未经测试。我为任何错别字/错误道歉。