将参数传递给pthread

时间:2010-04-17 10:08:43

标签: c multithreading unix pthreads

我有以下代码:

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

#define NUM_THREADS 100

struct thread_param {
    char *f1;
    char *f2;
    int x;
};

void *thread_function(void *arg){
    printf("%d\n", ((struct thread_param*)arg)->x);
}

int main(int argc, char *argvs[]){
    int i, thread_cr_res = 0, thread_join_res;
    pthread_t *threads;
    threads = malloc(100 * sizeof(*threads));
    if(threads == NULL){
        fprintf(stderr,"MALLOC THREADS ERROR");
        return (-1);
    }
    for(i = 0; i < NUM_THREADS; i++){
        struct thread_param *tp;
        if((tp = malloc(sizeof(*tp))) == NULL){
            fprintf(stderr,"MALLOC THREAD_PARAM ERROR");
            return (-1);
        }
        tp->f1 = "f1";
        tp->f2 = "f2";
        tp->x = i;
        thread_cr_res = pthread_create(&threads[i], 
                    NULL, 
                    thread_function, 
                    (void*)tp);
        if(thread_cr_res != 0){
            fprintf(stderr,"THREAD CREATE ERROR");
            return (-1);
        }
    }
    return (0);
}

我想要实现的是从线程打印0到99之间的所有数字。此外,我正在尝试一种方法将结构作为线程输入参数传递。

我发现古玩的是,并非所有数字都显示出来,例如:

 ./a.out | grep 9
9
19
29
39
49

有时一些数字会显示两次:

...
75
74
89
77
78
79
91
91

你能解释一下我为什么会这样吗? 没有显示错误。

LATER EDIT: 我使用pthread_join重写了@Yasir建议的代码。新代码如下所示:

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

#define NUM_THREADS 100

struct thread_param {
    char *f1;
    char *f2;
    int x;
};

void *thread_function(void *arg){
    printf("%d\n", ((struct thread_param*)arg)->x);
}

int main(int argc, char *argvs[]){
    int i, thread_cr_res = 0, thread_join_res;
    pthread_t *threads;
    threads = malloc(100 * sizeof(*threads));
    if(threads == NULL){
        fprintf(stderr,"MALLOC THREADS ERROR");
        return (-1);
    }
    for(i = 0; i < NUM_THREADS; i++){
        struct thread_param *tp;
        if((tp = malloc(sizeof(*tp))) == NULL){
            fprintf(stderr,"MALLOC THREAD_PARAM ERROR");
            return (-1);
        }
        tp->f1 = "f1";
        tp->f2 = "f2";
        tp->x = i;
        thread_cr_res = pthread_create(&threads[i], 
                    NULL, 
                    thread_function, 
                    (void*)tp);
        if(thread_cr_res != 0){
            fprintf(stderr,"THREAD CREATE ERROR");
            return (-1);
        }
    }
    /* Later edit, joining the threads */
    for (i = 0; i < NUM_THREADS; i++){
        thread_join_res = pthread_join(threads[i], NULL);
        if(thread_join_res != 0){
            fprintf(stderr, "JOIN ERROR");
            return (-1);
        }       
    }
    return (0);
}

后:

./a.out | sort
0
1
10
11
12
13
14
15
16
17
18
19
2
20
21
22
23
24
25
26
27
28
29
3
30
31
32
33
34
35
36
37
38
39
4
40
41
42
43
44
45
46
47
48
49
5
50
51
52
53
54
55
56
57
58
59
6
60
61
62
63
64
65
66
67
68
69
7
70
71
72
73
74
75
76
77
78
79
8
80
81
82
83
84
85
86
87
88
89
9
90
91
92
93
94
95
96
97
98
99

代码表现得像它应该的那样。我仍然无法解释为什么代码的第一个版本输出重复项。

2 个答案:

答案 0 :(得分:2)

使用int pthread_join(pthread_t thread, void **value_ptr)等待线程终止,以便在主线程退出之前获得所有结果。同样由于sizeof(*tp),你最终得到了这个结构的指针大小,这个结构在32位系统上长4个字节。这可能会重写内存中的其他结构。 sizeof(thread_param)会对我更有意义。 tp->f1 = "f1";也指一个常量字符串。 I. e。你没有在结构中保存字符串,而是为所有thread_param结构使用相同的缓冲区。如果"f1"是指向变量缓冲区的指针,这将是不安全的。

UPD:是的,关于大小的评论是正确的。

答案 1 :(得分:1)

  

代码表现得像它应该的那样。我仍然无法解释为什么代码的第一个版本输出重复项。

这可能与stdio如何跨线程工作有关:为了不破坏输出(通常是任何其他流),stdio使用锁定。如果你的主线程退出,可能会发生坏事,比如关闭流,这些流必须由其他线程重新打开/刷新。

请注意,由于存在stdio函数的锁定,因此存在争用,并且printf()调用成为一种同步点,它将改变程序的工作方式。