一:关于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_join和pthread_detach的用法

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

  2. linux线程之pthread_join和pthread_detach

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

  3. linux中pthread_join()与pthread_detach()

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

  4. pthread_join与pthread_detach细节问题

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

  5. Linux 线程--那一年, 我们一起忽视的pthread_join

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

  6. pthread_mutex_t

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

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

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

  8. 在Linux中使用线程

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

  9. pthread_attr_setdetachstate

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

随机推荐

  1. java中的日志组件-log4j

    1.为什么使用日志组件 Log4J是Apache的一个开放源代码项目,它是一个日志操作包,通过使用Log4J,可以指定日志信息输出的目的地,如控制台.文件.CUI组件.NT的事件记录器:还可以控制每一 ...

  2. struts中的请求数据自动封装

    Struts 2框架会将表单的参数以同名的方式设置给对应Action的属性中.该工作主要是由Parameters拦截器做的.而该拦截器中已经自动的实现了String到基本数据类型之间的转换工作.在st ...

  3. Hibernate4 No Session found for current thread原因

    Hibernate4 与 spring3 集成之后, 如果在取得session 的地方使用了getCurrentSession, 可能会报一个错:“No Session found for curre ...

  4. HDU 4627 E(Contest #3)

    Description There are many unsolvable problem in the world.It could be about one or about zero.But t ...

  5. 【转发】Linux下清除系统日志方法

    摘要:相信大家都是用过Windows的人.对于Windows下饱受诟病的各种垃圾文件都需要自己想办法删除,不然你的系统将会变得越来越大,越来越迟钝!windows怎么清理垃圾相信大家都知道的,那么li ...

  6. SharePoint 2013 开发——开发并部署第一个APP

    博客地址:http://blog.csdn.net/FoxDave 本篇我们开始对开发APP应用程序进行了解. 本篇基于本地SharePoint环境(如果是Office 365的话会方便许多),需 ...

  7. RAID-4与模2和

    在网络传输和磁盘数据管理中经常涉及到的所谓奇偶校验:每N个bit之后加上一个bit保证这N + 1bit的模2和为0(也叫异或,一个意思) 而如果这其中出现了单bit错, 直接导致校验出差,出现偶数b ...

  8. HTML中使用CSS的方法

    行内样式表 <html> <head> <title>行内样式表</title> </head> <body> <p st ...

  9. linux常用命令:1文件处理命令

    文件处理命令 1.命令格式 命令格式:命令 [-选项]  [参数] 例:ls  -la /etc 说明:1)个别命令使用不遵循此格式 2)档有多个选项时,可以写在一起 3)简化选项与完整选项 2.目录 ...

  10. Generic method return type

    Here's the Animal class: public class Animal{ private Map<String,Animal> friends =new HashMap& ...