`
huoyj
  • 浏览: 89611 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

pthread_join和pthread_detach的用法

 
阅读更多
//从别处拷贝过来的,只作为自己查看方便,原作者不详,请谅解。

一:关于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()),从而导致进程及其所有线程结束运行。
分享到:
评论

相关推荐

    Windows可使用的pthread库

    pthread-win32是pthread库的一个移植版本,它为Windows操作系统提供了与Posix线程兼容的API,使得C和C++开发者能够在Windows上使用pthread相关的函数,如`pthread_create`、`pthread_join`、`pthread_mutex_lock`等...

    windows 下的pthread 库

    其中,`pthread`(Posix Threads)是UNIX和类UNIX操作系统上广泛使用的多线程API,它定义了一套标准的接口,使得开发者能够在不同的平台上创建和管理线程。尽管`pthread`最初设计用于符合POSIX标准的操作系统,但...

    linux中的线程源代码

    7. **线程分离**:通过`pthread_detach()`函数,可以将线程设置为分离状态,这样线程结束后,系统会自动清理资源,无需调用`pthread_join()`。 8. **线程ID**:`pthread_self()`返回当前线程的ID,`pthread_equal()...

    Linux pthread相关函数用法说明(包括发生段错误的原因以及对策等)

    根据给定文件的信息,本文将深入探讨Linux下pthread库中几个关键函数的使用方法,并针对“段错误”这一常见问题进行分析与对策建议。 ### 1. pthread_create #### 函数原型 ```c int pthread_create(pthread_t *...

    pthread经典用法

    本文将深入探讨pthread的基本用法,包括线程创建、线程返回值处理、以及互斥锁(Mutex)的使用,帮助开发者更好地理解和掌握这一关键的多线程接口。 一、pthread线程创建与管理 pthread库提供了创建和管理线程的...

    pthread手册.doc

    ### pthread使用手册知识点详解 #### 一、pthread基础概述 `pthread`是POSIX线程的简称,是一种标准的线程编程接口,广泛应用...以上是关于`pthread`使用手册的基本知识点总结,希望对学习和使用`pthread`有所帮助。

    Linux系统编程-(pthread)线程的使用案例(分离属性、清理函数等).pdf

    本篇将探讨如何在Linux环境下使用pthread库创建和管理线程,包括线程的创建、接收子线程返回值以及设置线程的分离属性。 1. **线程创建**: 线程的创建是通过调用`pthread_create`函数来实现的。函数原型为: ```c ...

    pthread库文档_急速版

    7. **线程分离**:通过pthread_detach()函数,线程可以设置为分离状态,一旦结束,系统会自动清理相关资源,无需其他线程join。 8. **线程标识与当前线程**:pthread_self()返回当前线程的ID,pthread_equal()用于...

    linux 多进程多线程编程

    在使用 pthread_exit 和 pthread_join 函数时,需要注意以下几点: * pthread_exit 函数只能在线程内部调用,否则会导致程序崩溃。 * pthread_join 函数可以在任何线程中调用,但只能等待其他线程的终止。 5. 分离...

    pthread代码实例

    5. **线程分离**:`pthread_detach()`函数允许将线程设置为独立运行,线程结束时资源自动回收,无需主线程join。这对于不需要等待线程结束的情况很有用。 6. **线程属性**:通过`pthread_attr_init()`和`pthread_...

    POSIX Pthread 编程资料大全

    线程可以通过`pthread_create()`创建,通过`pthread_join()`或`pthread_detach()`来结束。`pthread_join()`会阻塞调用线程直到目标线程结束,而`pthread_detach()`则允许线程结束后资源自动释放。 三、线程同步 ...

    日常记录学习,基础知识,学习笔记

    在编写多线程程序时,合理地使用`pthread_self()`、`pthread_join()`和`pthread_detach()`,以及妥善处理端口冲突,可以有效地优化程序性能并避免资源浪费。同时,熟悉这些基本工具和概念,也有助于排查和解决实际...

    LINUX线程函数大全.pdf

    本手册将详细讲解每个线程函数的使用方法、参数设置、返回值等信息,从而帮助开发者更好地掌握 LINUX 线程编程技术。 一、线程创建 线程创建是 LINUX 线程编程的基础,pthread_create 函数是创建线程的主要函数。...

    Posix Pthread API 总结文档

    本文档总结了 Posix Pthread API 的主要函数和使用方法,旨在帮助开发者快速掌握 Posix Pthread API 的使用。 一、 基本线程编程 在 Posix Pthread API 中,线程是轻量级的进程,可以并发执行以提高系统性能。创建...

    pthread_pool2.zip

    POSIX线程是跨平台的线程API,它提供了`pthread_create()`、`pthread_join()`等函数来创建和管理线程。与C++11的`std::thread`不同,pthread API更加底层,灵活性更高,但也需要更多的手动管理。 线程池的实现通常...

    线程基本编程——线程函数大全.doc

    线程编程需要使用一些特殊的函数来创建、管理和控制线程的生命周期。在本文中,我们将总结线程基本编程中的一些重要函数。 1. 创建线程 pthread_create pthread_create 函数用于创建一个新的线程。它需要四个参数...

    Posix线程编程指南

    如果设置为detach状态(PTHREAD_CREATE_DETACH),线程将在结束时自动清理资源,且无法再用`pthread_join()`。`__schedpolicy`和`__schedparam`用于设置线程的调度策略和优先级,如非实时(SCHED_OTHER)、轮转...

    LinuxPthread实例详解及学习文档

    3. **线程 join 和 detach**:`pthread_join()`函数用于等待线程结束,而`pthread_detach()`可以使线程在结束后自动清理资源,无需其他线程join。 4. **线程属性**:`pthread_attr_t`结构体用于设置线程属性,如...

    LINUX线程函数大全[定义].pdf

    总的来说,Linux线程编程涉及的函数包括但不限于`pthread_create`、`pthread_join`、`pthread_detach`和`pthread_key_create`,它们共同构成了线程管理的核心。理解和熟练掌握这些函数的使用是编写多线程应用程序的...

Global site tag (gtag.js) - Google Analytics