pthread_join和pthread_detach的用法(转)

时间:2023-02-10 08:35:28

一:关于join 
join 
join是三种同步线程的方式之一。另外两种分别是互斥锁(mutex)和条件变量(condition variable)。 
调用pthread_join()将阻塞自己,一直到要等待加入的线程运行结束。 
可以用pthread_join()获取线程的返回值。 
一个线程对应一个pthread_join()调用,对同一个线程进行多次pthread_join()调用是逻辑错误。 
join or detach 
线程分两种:一种可以join,另一种不可以。该属性在创建线程的时候指定。 
joinable线程可在创建后,用pthread_detach()显式地分离。但分离后不可以再合并。该操作不可逆。 
为了确保移植性,在创建线程时,最好显式指定其join或detach属性。似乎不是所有POSIX实现都是用joinable作默认。

二: 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,则该线程运行结束后会自动释放所有资源。

三:pthread_join 
调用pthread_join的线程会阻塞,直到指定的线程返回,调用了pthread_exit,或者被取消。 
    如果线程简单的返回,那么rval_ptr被设置成线程的返回值,参见范例1;如果调用了pthread_exit,则可将一个无类型指针返回,在pthread_join中对其进行访问,参见范例2;如果线程被取消,rval_ptr被设置成PTHREAD_CANCELED。 
    如果我们不关心线程的返回值,那么我们可以把rval_ptr设置为NULL。

范例1: 
#include <pthread.h> 
#include <string.h>

void *thr_fn1(void *arg) 

    printf(“thread 1 returning.\n”); 
    return((void *)1); 
}

void *thr_fn2(void *arg) 

    printf(“thread 2 exiting.\n”); 
    return((void *)2); 
}

int main() 

    pthread_t tid1,tid2; 
    void *tret; 
    pthread_create(&tid1,NULL,thr_fn1,NULL); 
    pthread_create(&tid2,NULL,thr_fn2,NULL); 
    pthread_join(tid1,&tret); 
    printf(“thread 1 exit code %d\n”,(int)tret); 
    pthread_join(tid2,&tret); 
    printf(“thread 2 exit code %d\n”,(int)tret); 
    exit(0); 
}

运行结果: 
thread 1 returning. 
thread 1 exit code 1. 
thread 2 exiting. 
thread 2 exit code 2.

范例2: 
#include <stdio.h> 
#include <pthread.h>

void thread1(char s[]) 

        printf("This is a pthread1.\n"); 
        printf("%s\n",s); 
        pthread_exit("Hello first!");  //结束线程,返回一个值。 
}

void thread2(char s[]) 

        printf("This is a pthread2.\n"); 
        printf("%s\n",s); 
        pthread_exit("Hello second!"); 
}

int main(void) 

        pthread_t id1,id2; 
        void *a1,*a2; 
        int i,ret1,ret2; 
        char s1[]="This is first thread!"; 
        char s2[]="This is second thread!"; 
        ret1=pthread_create(&id1,NULL,(void *) thread1,s1);

ret2=pthread_create(&id2,NULL,(void *) thread2,s2);

if(ret1!=0){ 
                printf ("Create pthread1 error!\n"); 
                exit (1); 
        } 
        pthread_join(id1,&a1);

printf("%s\n",(char*)a1);

if(ret2!=0){ 
                printf ("Create pthread2 error!\n"); 
                exit (1); 
        } 
        printf("This is the  main process.\n"); 
        pthread_join(id2,&a2); 
        printf("%s\n",(char*)a2); 
        return (0); 
}

运行结果: 
[****@XD**** c]$ ./example 
This is a pthread1. 
This is first thread! 
Hello first! 
This is the main process. 
This is a pthread2.

<参考资料语>

一般情况下,进程中各个线程的运行都是相互独立的,线程的终止并不会通知,也不会影响其他线程,终止的线程所占用的资源也并不会随着线程的终止而得到释 放。正如进程之间可以用wait()系统调用来同步终止并释放资源一样,线程之间也有类似机制,那就是pthread_join()函数

pthread_join()的调用者将挂起并等待th线程终止,retval是pthread_exit()调用者线程(线程ID为th)的返回值,如 果thread_return不为NULL,则*thread_return=retval。需要注意的是一个线程仅允许唯一的一个线程使用 pthread_join()等待它的终止,并且被等待的线程应该处于可join状态,即非DETACHED状态

如果进程中的某个线程执行了pthread_detach(th),则th线程将处于DETACHED状态,这使得th线程在结束运行时自行释放所占用的 内存资源,同时也无法由pthread_join()同步,pthread_detach()执行之后,对th请求pthread_join()将返回错误

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

3) 主线程用pthread_exit还是return

用pthread_exit只会使主线程自身退出,产生的子线程继续执行;用return则所有线程退出。

综合以上要想让子线程总能完整执行(不会中途退出),一种方法是在主线程中调用pthread_join对其等待,即pthread_create/pthread_join/pthread_exit或return;一种方法是在主线程退出时使用pthread_exit,这样子线程能继续执行,即pthread_create/pthread_detach/pthread_exit;还有一种是pthread_create/pthread_detach/return,这时就要保证主线程不能退出,至少是子线程完成前不能退出。现在的项目中用的就是第三种方法,主线程是一个死循环,子线程有的是死循环有的不是。

<参考资料语>

理论上说,pthread_exit()和线程宿体函数退出的功能是相同的,函数结束时会在内部自动调用pthread_exit()来清理线程相关的资源。但实际上二者由于编译器的处理有很大的不同。

在进程主函数(main())中调用pthread_exit(),只会使主函数所在的线程(可以说是进程的主线程)退出;而如果是return,编译器将使其调用进程退出的代码(如_exit()),从而导致进程及其所有线程结束运行。

pthread_join和pthread_detach的用法(转)的更多相关文章

  1. pthread&lowbar;join和pthread&lowbar;detach的用法

    //从别处拷贝过来的,只作为自己查看方便,原作者不详,请谅解. 一:关于join join join是三种同步线程的方式之一.另外两种分别是互斥锁(mutex)和条件变量(condition vari ...

  2. linux线程之pthread&lowbar;join和pthread&lowbar;detach

    在任何一个时间点上,线程是可结合的(joinable)或者是分离的(detached).一个可结合的线程能够被其他线程收回其资源和杀死.在 被其他线程回收之前,它的存储器资源(例如栈)是不释放的.相反 ...

  3. linux中pthread&lowbar;join&lpar;&rpar;与pthread&lowbar;detach&lpar;&rpar;

    1.linux线程执行和windows不同,pthread有两种状态joinable状态和unjoinable状态, 如果线程是joinable状态,当线程函数自己返回退出时或pthread_exit ...

  4. pthread&lowbar;join与pthread&lowbar;detach细节问题

    http://www.360doc.com/content/13/0106/09/9171956_258497083.shtml pthread_t    pthr; pthread_create(& ...

  5. Linux 线程--那一年&comma; 我们一起忽视的pthread&lowbar;join

    前言: 通过linux的pthread库, 相信大家对创建/销毁线程肯定很熟悉, 不过对pthread_join是否知道的更多呢?实验: 先编写一个常规的程序 #include <pthread ...

  6. pthread&lowbar;mutex&lowbar;t

     在Linux中使用线程 http://blog.csdn.net/jiajun2001/article/details/12624923 :LINUX就是这个范围作者   原创作品,允许转载,转载时 ...

  7. Linux系统编程(27)——线程控制

    进程在各自独立的地址空间中运行,进程之间共享数据需要用mmap或者进程间通信机制,那么如何在一个进程的地址空间中执行多个线程呢.有些情况需要在一个进程中同时执行多个控制流程,这时候线程就派上了用场,比 ...

  8. 在Linux中使用线程

    我并不假定你会使用Linux的线程,所以在这里就简单的介绍一下.如果你之前有过多线程方面的编程经验,完全可以忽略本文的内容,因为它非常的初级. 首先说明一下,在Linux编写多线程程序需要包含头文件p ...

  9. pthread&lowbar;attr&lowbar;setdetachstate

    pthread_create函数可以指定新创建线程的属性. pthread_attr_setdetachstate() set  detach state attribute in thread at ...

随机推荐

  1. Ubuntu14&period;04 64位配置Caffe 教程(基于CUDA7&period;5)

    最新博客地址已转到: http://blog.csdn.net/zzlyw?viewmode=contents   ------------------------------------------ ...

  2. android assets文件夹浅谈

    ---恢复内容开始--- 最近在研究assets文件夹的一些属性跟使用方法.根据网上一些文章.实例做一下汇总,拿出来跟大家分享下,有不足的地方还请多多指教. 首先了解一下assets是干什么用的,as ...

  3. hi3531播放1080p60f, 延迟越来越大的问题与解决办法

    问题 hi3531播放1080p60f, 延迟越来越大 左边屏幕是ffplay播放的,右边屏幕是3531播放的 数据是udp组播 mpegts, h264 12M码流 原因 经过测试发现: 解码器中缓 ...

  4. lwip移植到stm32上-enc28j60,103mcu(2)

    前面小玩了一下ucos和lwip,但是都还不是真正的网络多任务,真正的网络多任务应该是什么样子的呢?应该是有一个专门的任务负责网络的通讯,他负责将数据发送出去,将数据接收回来,而其他的需要用到网络的任 ...

  5. swift 运算符快速学习(建议懂OC或者C语言的伙伴学习参考)

    昨晚看了swift 的运算符的知识点,先大概说一下,这个点和 c 或者oc 的算运符知识点一样,都是最基础最基础的.其他的最基本的加减乘除就不多说了.注意的有几点点..先说求余数运算: 一 :求余数运 ...

  6. 【SHOI2012】魔法树(树链剖分,线段树)

    [SHOI2012]魔法树 题面 BZOJ上找不到这道题目 只有洛谷上有.. 所以粘贴洛谷的题面 题解 树链剖分之后直接维护线段树就可以了 树链剖分良心模板题 #include<iostream ...

  7. httpclient方式调用接口

    public class ToInterface { /** * post方式提交表单(模拟用户登录请求) */ public static void postForm() { // 创建默认的htt ...

  8. Python&plus;turtle交互式绘图:可以用鼠标拖动的小海龟

    下面是我画海龟的过程: (1)打开python: 2.调用turtle库,先设置一些基础设置,与一个画龟的函数 from turtle import Screen,Turtle,mainloop cl ...

  9. 深入浅出MongoDB应用实战开发

    写在前面的话: 这篇文章会有点长,谨此记录自己昨天一整天看完<深入浅出MongoDB应用实战开发>视频时的笔记.只是在开始,得先抛出一个困扰自己很长时间的问题:“带双引号的和不带双引号的j ...

  10. 深入浅出 JMS&lpar;一&rpar; - JMS 基本概念

    深入浅出 JMS(一) - JMS 基本概念 一.JMS 是个什么鬼 JMS 是 Java Message Service 的简称,即 Java 消息服务.什么是消息服务呢,我们来看一下 Oracle ...