正确使用POSIX' pthread_exit和pthread_join

时间:2013-08-09 18:25:23

标签: c pthreads

我正在尝试从pthread返回值并捕获该值的概念,但我无法理解发生了什么,或者如何使其工作。我有这个创建单个线程的简单程序,这个线程以int值100退出,然后我尝试用pthread_join捕获该值:

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

void *doStuff(void *param) {
    int a = 100;
    pthread_exit(a);
}

void main() {
    pthread_t thread;
    int a;
    pthread_create(&thread, NULL, doStuff, NULL);
    pthread_join(thread, &a);
    printf("%d\n", a);
}

它有效,但抛出了一些警告:

./teste.c: In function ‘doStuff’:
./teste.c:7:2: warning: passing argument 1 of ‘pthread_exit’ makes pointer from integer without a cast [enabled by default]
In file included from ./teste.c:2:0:
/usr/include/pthread.h:241:13: note: expected ‘void *’ but argument is of type ‘int’
./teste.c: In function ‘main’:
./teste.c:17:2: warning: passing argument 2 of ‘pthread_join’ from incompatible pointer type [enabled by default]
In file included from ./teste.c:2:0:
/usr/include/pthread.h:249:12: note: expected ‘void **’ but argument is of type ‘int *’

我不明白为什么我会收到这些警告,老实说,我不明白为什么这也有用,因为我认为我必须在pthread_exit上返回一个void指针。

这是一个简单的例子,我正在努力工作,以便我能够完成我正在尝试创建的另一个程序,其中我将有一个线程数组,每个程序都计算一个单浮点值,我想使用pthread_exit和pthread_join将每个计算值存储到浮点数组中,但我真的不知道如何将pthread_join中的值存储到数组中。

2 个答案:

答案 0 :(得分:5)

pthread_exit需要void*,而非int。 (请注意,调用pthread_exit(x)与从线程函数中返回x相同。)

对您的问题最简单的解决方法是向线程函数传递一个指向int的指针,用于存储生成的值:

void *doStuff(void *param) {
    int a = 100;
    *(int*)param = a;
    return NULL;
}

int main(void) {
    pthread_t thread;
    int a;
    pthread_create(&thread, NULL, doStuff, &a);
    pthread_join(thread, NULL);
    printf("%d\n", a);
}

编辑:如果你真的需要使用线程函数的返回值来传达结果,你有几个选择。

(1)将返回值输入和输出void*

void *doStuff(void *param) {
    int a = 100;
    return (void*)a;
}

int main(void) {
    pthread_t thread;
    pthread_create(&thread, NULL, doStuff, NULL);
    void* ptr;
    pthread_join(thread, &ptr);
    int a = (int)ptr;
    printf("%d\n", a);
}

这感觉有点hackish,因为它是。如果您确定从void*转换为int将在您将要定位的每个平台上保留void *doStuff(void *param) { int a = 100; int* ptr = malloc(sizeof(*ptr)); assert(ptr); /* I'm lazy, sue me. */ *ptr = a; return ptr; } int main(void) { pthread_t thread; pthread_create(&thread, NULL, doStuff, NULL); void* ptr; pthread_join(thread, &ptr); int a = *(int*)ptr; free(ptr); printf("%d\n", a); } 的值,那么无论如何都要抛弃。

(2)返回一个指向包含返回值的动态分配存储的指针:

struct foo {
  int input1;
  int input2;
  int result;
};

void *doStuff(void *param) {
    foo* f = param;
    f->result = f->input1 + f->input2;
    return NULL;
}

int main(void) {
    foo* ptr = malloc(sizeof(*ptr));
    assert(ptr);
    ptr->input1 = 5;
    ptr->input2 = 3;

    pthread_t thread;
    pthread_create(&thread, NULL, doStuff, ptr);
    pthread_join(thread, NULL);

    printf("%d\n", ptr->result);
    free(ptr);
}

(3)创建一个结构来封装线程的所有输入/输出参数(重量级,但非常明确):

{{1}}

答案 1 :(得分:0)

只需添加一种方法即可避免所有警告。我实际上通过阅读多个SO答案得到了这个解决方案。

void *thread_fn(void *arg) {
    int a = 100;
    return (void*)(intptr_t)a;
}

int main(void) {
    pthread_t thread;
    void* ptr;
    int a;
    pthread_create(&thread, NULL, thread_fn, &a);
    pthread_join(thread, &ptr);
    a = (intptr_t)ptr;
    printf("%d\n", a);
}

在上面的代码片段中,return (void*)(intptr_t)a;这里我们首先输入类型转换整数以获得与指针(intptr_t)大小相同的整数类型。然后我们现在可以将它强制转换为void指针。 a = (intptr_t)ptr;

的情况也是如此