曲径通幽论坛

标题: pthread_join()--等待一个线程结束 [打印本页]

作者: beyes    时间: 2009-6-28 22:19
标题: pthread_join()--等待一个线程结束
线程终止时,一个需要注意的问题是线程间的同步问题。一般情况下,进程中各个线程的运行是相互独立的,线程的终止并不会相互通知,也不会影响其他线程,终止的线程所占用的资源不会随着线程的终止而归还系统,而是仍然为线程所在的进程持有。正如进程间可以用 wait()系统调用来等待其他进程结束一样,线程也有类似的函数:pthread_join(),在 pthread.h 头文件中声明如下:
#include <pthread.h>
int pthread_join(pthread_t th, void *thread_return);
int pthread_tetach(pthread_t th);
函数 pthread_join() 用来等待一个线程的结束。pthread_join() 的调用者将被挂起并等待 th 线程终止,如果 thread_return 不为 NULL,则 *thread_return=retval。需要注意的是,一个线程仅允许一个线程使用 pthread_join() 等待它的终止,并且被等待的线程应该处于可 join 状态,即非 DETACHED 状态。DETACHED 状态是指对某个线程执行 pthread_detach() 后其所处的状态。处于 DETACHED 状态的线程无法由 pthread_join() 同步。

一个可 "join" 的线程所占用的内存仅当有线程对其执行了 phread_join() 后才会释放,因此为了避免内存泄露,所有线程终止时,要么设为 DETACHED ,要么使用 pthread_join() 来回收资源。

注意:一个线程不能被多个线程等待,否则第一个接收信号的线程成功返回,其余调用 pthread_join() 的线程返回错误代码 ESRCH 。

测试程序
#include <stdio.h>
#include <pthread.h>

void assisthread(void *arg)
{
    printf("I am helping to do some jobs\n");
    sleep(3);
    pthread_exit(0);
}

int main(void)
{
    pthread_t    assistthid;
    int        status;
   
    pthread_create(&assistthid, NULL, (void *)assisthread, NULL);
    pthread_join(assistthid, (void *)&status);
    printf("assistthid's exit is caused %d\n", status);

    return 0;
}
运行及输出
beyes@linux-beyes:~/C/base> ./jointhread.exe
I am helping to do some jobs
assistthid's exit is caused 0
说明
从运行结果可以看出 pthread_join() 会阻塞主线程,等待线程 assisthread 结束。pthread_exit() 结束时的退出码是0,pthread_join 得出的 status 也为 0,两者是一致的。

例-2
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void *thread_malloc (char *parameter)
{
    int *p;
    p = (int *)malloc (10 * sizeof(int));    /*申请空间*/
    printf ("传进来的参数是 %s\n", parameter);
    printf ("该线程ID是 %u\n", pthread_self());
    memset (p, 'c', 10);
    printf ("刚才申请的空间首地址为: 0x%x\n", p);
    pthread_exit (p);    //退出线程,返回申请空间首址
}

int main (int argc, char **argv)
{
    int error;
    int *temptr;
    pthread_t thread_id;

    /*创建线程*/
    pthread_create (&thread_id, NULL, (void *)*thread_malloc, "thread malloc");

    /*线程结束时返回值存放在pthread_join()函数的第 2 个参数里*/
    if (error = pthread_join (thread_id, (void **)&temptr)) {
        perror ("thread_join");
        exit (EXIT_FAILURE);
    }

    printf ("线程返回的指针地址是: 0x%x\n", temptr);
    printf ("线程申请的空间没被回收,现在打印出此空间第一个字节的值:%c\n", *temptr);

    *temptr = 'd';    //改变堆空间值,测试是否可用
    printf ("更改后的值为: %c\n", *temptr);

    free (temptr);    //释放该堆空间

    return (0);
}
运行与输出
./thread_exit_test
传进来的参数是 thread malloc
该线程ID是 3075955568
刚才申请的空间首地址为: 0x804b098
线程返回的指针地址是: 0x804b098
线程申请的空间没被回收,现在打印出此空间第一个字节的值:c
更改后的值为: d
说明:
上面的代码验证了线程退出时全局变量、局部变量和堆空间是如何管理的。在上面程序中,首先在主线程中创建一个新线程,在新线程中申请一段堆空间并赋值,然后作为该线程的返回值。在主线程中,等待该子线程结束,并存储其退出状态。此程序如果没有出现异常,那么子线程中申请的堆空间在主线程中也可以访问并释放,这说明了子线程退出时仅释放其私有的栈空间(局部数据)。显然,位于数据段的全局数据是不会在线程退出时释放的,只有当进程退出时才释放。




欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2