正确使用POSIX的pthread_exit和pthread_join

dev*_*ull 1 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);
}
Run Code Online (Sandbox Code Playgroud)

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

./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 *’
Run Code Online (Sandbox Code Playgroud)

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

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

Cas*_*sey 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);
}
Run Code Online (Sandbox Code Playgroud)

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

(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);
}
Run Code Online (Sandbox Code Playgroud)

这感觉有点hackish,因为它是.如果您确定转换为to-and-from void*将保留int您将要定位的每个平台上的值,那么无论如何都要抛弃.

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

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);
}
Run Code Online (Sandbox Code Playgroud)

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

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);
}
Run Code Online (Sandbox Code Playgroud)