关于pthread_join

函数原形:

#include <pthread.h>
int pthread_join(pthread_t thread,void **retval);
return 0 on success,or a positive error number on error

调用pthread_join的线程会阻塞,如果线程已经终止,pthread_join会立即返回。
如果线程简单的返回,那么rval_ptr被设置成线程的返回值;如果调用了pthread_exit,则可将一个无类型指针返回,在pthread_join中对其进行访问;如果线程被取消,rval_ptr被设置成PTHREAD_CANCELED。
如果我们不关心线程的返回值,那么我们可以把rval_ptr设置为NULL。
调用pthread_join()将阻塞自己,一直到要等待加入的线程运行结束。
一个线程对应一个pthread_join()调用,对同一个线程进行多次pthread_join()调用是逻辑错误。
线程分两种:一种可以join,另一种不可以。该属性在创建线程的时候指定。
joinable线程可在创建后,用pthread_detach()显式地分离。但分离后不可以再合并。该操作不可逆。
为了确保移植性,在创建线程时,最好显式指定其join或detach属性。

pthread_detach

创建一个线程默认的状态是joinable, 如果一个线程结束运行但没有被join,则它的状态类似于进程中的Zombie Process,即还有一部分资源没有被回收,所以创建线程者应该调用pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源(类似于wait,waitpid)
但是调用pthread_join(pthread_id)后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此,比如在Web服务器中当主线程为每个新来的链接创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的链接),这时可以在子线程中加入代码
pthread_detach(pthread_self())
或者父线程调用
pthread_detach(thread_id)
这将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源。

示例一

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

static void * threadFunc(void *arg)
{
    char *s = (char *)arg;
    printf("%s\n",s);
    return (void *)strlen(s);
}

int main(int argc, char *argv[])
{
    pthread_t t1;
    void *res;
    int s;

    s = pthread_create(&t1, NULL, threadFunc, "Hello world\n");
    if (s != 0)
    {
        fprintf(stderr, "Error creating thread\n");
        return 1;
    }

    printf("Message from main()\n");
    s = pthread_join(t1, &res);
    if (s != 0)
    {
        fprintf(stderr, "Error joining thread\n");
        return 2;
    }

    printf("Thread returned %ld\n", (long) res);

    exit(EXIT_SUCCESS);
}

程序输出:

Message from main()
Hello world

Thread returned 12

示例二

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

/* this function is run by the second thread */
void *inc_x(void *x_void_ptr)
{

/* increment x to 100 */
int *x_ptr = (int *)x_void_ptr;
while(++(*x_ptr) < 100);

printf("x increment finished\n");

/* the function must return something - NULL will do */
return NULL;

}

int main()
{

int x = 0, y = 0;

/* show the initial values of x and y */
printf("x: %d, y: %d\n", x, y);

/* this variable is our reference to the second thread */
pthread_t inc_x_thread;

/* create a second thread which executes inc_x(&x) */
if(pthread_create(&inc_x_thread, NULL, inc_x, &x)) {

fprintf(stderr, "Error creating thread\n");
return 1;

}
/* increment y to 100 in the first thread */
while(++y < 100);

printf("y increment finished\n");

/* wait for the second thread to finish */
if(pthread_join(inc_x_thread, NULL)) {

fprintf(stderr, "Error joining thread\n");
return 2;

}

/* show the results - x is now 100 thanks to the second thread */
printf("x: %d, y: %d\n", x, y);

return 0;

}

输出:

x: 0, y: 0
y increment finished
x increment finished
x: 100, y: 100