pthread_join使一个线程等待另一个线程结束。
  代码中如果没有pthread_join;主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。

  所有线程都有一个线程号,也就是threadid,其类型为pthread_t。 通过调用pthread_self()函数可以获得自身的线程号。

  如果你的主线程,也就是main函数执行的那个线程,在你其他线程退出之前就已经退出,那么带来的bug则不可估量。通过pthread_join函数会让主线程阻塞,直到所有线程都已经退出。

  int pthread_join(pthread_t thread, void **value_ptr);
    thread:等待退出线程的线程号。
    value_ptr:退出线程的返回值。

  可以通过pthread_join()函数来使主线程阻塞等待其他线程退出,这样主线程可以清理其他线程的环境。但是还有一些线程,更喜欢自己来清理退出 的状态,他们也不愿意主线程调用pthread_join来等待他们。我们将这一类线程的属性称为detached(分离的)。如果我们在调用 pthread_create()函数的时候将属性设置为NULL,则表明我们希望所创建的线程采用默认的属性,也就是jionable(此时不是detached)。

如果需要将属性 设置为detached。则应该如下设定:

   pthread_attr_t  attr;

  pthread_attr_init(&attr);

  pthread_attr_setdetachstate(&attr,  PTHREAD_CREATE_DETACHED);

  pthread_create(&pthreadid,  &attr,  myprocess,  &arg);

警告:

  在线程设置为joinable后,可以调用pthread_detach()使之成为detached。但是相反的操作则不可以。还有,如果线程已经调用pthread_join()后,则再调用pthread_detach()则不会有任何效果。

线程可以通过自身执行结束来结束,也可以通过调用pthread_exit()来结束线程的执行。另外,线程甲可以被线程乙被动结束。这个通过调用pthread_cancel()来达到目的。

int pthread_cancel(pthread_t thread);

函数调用成功返回0。

当然,线程也不是被动的被别人结束。它可以通过设置自身的属性来决定如何结束

  线程的被动结束分为两种,一种是异步终结,另外一种是同步终结。异步终结就是当其他线程调用pthread_cancel的时候,线程就立刻被结束。而同 步终结则不会立刻终结,它会继续运行,直到到达下一个结束点(cancellation point)。当一个线程被按照默认的创建方式创建,那么它的属性是同步终结。

 

线程终止的三种方式:

1. 线程只是从启动例程中返回,返回值是线程的退出码;

2. 线程调用了pthread_exit函数;

3. 线程可以被同一进程中的其他线程取消。

**************************************************************

1 线程取消的定义

一般情况下,线程在其主体函数退出的时候会自动终止,但同时也可以因为接收到另一个线程发来的终止(取消)请求而强制终止。

2 线程取消的语义

1. 线程取消的方法是向目标线程发Cancel信号,但如何处理Cancel信号则由目标线程自己决定,或者忽略(当禁止取消时)、或者立即终止(当在取消点 或异步模式下)、或者继续运行至Cancelation-point(取消点,下面将描述),总之由不同的Cancelation状态决定。

2. 线程接收到CANCEL信号的缺省处理(即pthread_create()创建线程的缺省状态)是继续运行至取消点再处理(退出),或在异步方式下直接 退出。一个线程处理cancel请求的退出操作相当于pthread_exit(PTHREAD_CANCELED)。当然线程可以通过设置为 PTHREAD_CANCEL_DISABLE来拒绝处理cancel请求,稍后会提及。

3. 线程的取消与线程的工作方式(joinable或detached)无关。

3 取消点

根据POSIX标准,pthread_join()、 pthread_testcancel()、pthread_cond_wait()、 pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及read()、write()等会引起阻塞的系 统调用都是Cancelation-point,而其他pthread函数都不会引起Cancelation动作。但是pthread_cancel的手册页声称,由于LinuxThread库与C库结合得不好,因而目前C库函数都不是Cancelation-point;但CANCEL信号会使线程从阻塞的系统调用中退出,并置EINTR错误码,因此可以在需要作为Cancelation-point的系统调用前后调用pthread_testcancel(),从而达到POSIX标准所要求的目标,即如下代码段:  
pthread_testcancel();  
retcode = read(fd, buffer,length);  
pthread_testcancel();

使用前 须判断线程ID的有效性!即判断并保证:thrd != 0 否则有可能会出现“段错误”的异常!

但是pthread_cancel的手册页声称,由于LinuxThread库与C库结合得不好,因而目前C库函数(比如read())在linux中都不是Cancelation-point;但CANCEL信号会使线程从阻塞的系统调用中退出,并置EINTR错误码,因此可以在需要作为Cancelation-point的系统调用前后调用 pthread_testcancel(),从而达到POSIX标准所要求的目标,即如下代码段:

              pthread_testcancel();
retcode = read(fd, buffer, length);
pthread_testcancel();

 

4 程序设计方面的考虑

1. 如果线程处于无限循环中,且循环体内没有执行至取消点的必然路径,则线程无法由外部其他线程的取消请求而终止。因此在这样的循环体的必经路径上应该加入pthread_testcancel()调用。

2. 当pthread_cancel()返回时,线程未必已经取消,可能仅仅将请求发送给目标线程,而目标线程目前没有到达取消点,如果要知道线程在何时中止,就需要在取消它之后调用pthread_join()。有一个例外是当线程被detach后,不能这样处理:
a) 当join一个已经detached的线程时,返回EINVAL;
b) 如果join后该线程设置为detached,则detach将不起作用。
因此,如果知道一个线程可能会以分离方式运行,就不需要在pthread_cancel()后调用pthread_join()。

5 与线程取消相关的pthread函数

int pthread_cancel(pthread_t thread)
发送终止信号给thread线程,如果成功则返回0,否则为非0值。发送成功并不意味着thread会终止。

int pthread_setcancelstate(int state, int *oldstate)

置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)和
PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信号继续运行;old_state如果不为
NULL则存入原来的Cancel状态以便恢复。

int pthread_setcanceltype(int type, int *oldtype)

置本线程取消动作的执行时机,type有两种取值:PTHREAD_CANCEL_DEFFERED 和
PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和
立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。

void pthread_testcancel(void)
检查本线程是否处于Canceld状态,如果是,则进行取消动作,否则直接返回。

6 检测一个线程是否还活着的pthread函数

int pthread_kill(pthread_t thread, int sig)
向指定ID的线程发送sig信号,如果线程的代码内不做任何信号处理,则会按照信号默认的行为影响整个进程。也就是说,如果你给一个线程发送了SIGQUIT,但线程却没有实现signal处理函数,则整个进程退出。
pthread_kill(threadid, SIGKILL)也一样,他会杀死整个进程。
如果要获得正确的行为,就需要在线程内实现signal(SIGKILL,sig_handler)。
所以,如果int sig的参数不是0,那一定要清楚到底要干什么,而且一定要实现线程的信号处理函数,否则,就会影响整个进程。
那么,如果int sig的参数是0呢,这是一个保留信号,一个作用就是用来判断线程是不是还活着。
我们来看一下pthread_kill的返回值:
线程仍然活着:0
线程已不存在:ESRCH
信号不合法:EINVAL

 

 

linux线程之pthread_join的更多相关文章

  1. linux线程之pthread_join和pthread_detach

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

  2. Linux编程之ICMP洪水攻击

    我的上一篇文章<Linux编程之PING的实现>里使用ICMP协议实现了PING的程序,ICMP除了实现这么一个PING程序,还有哪些不为人知或者好玩的用途?这里我将介绍ICMP另一个很有 ...

  3. iOS多线程之8.NSOPeration的其他用法

      本文主要对NSOPeration的一些重点属性和方法做出介绍,以便大家可以更好的使用NSOPeration. 1.添加依赖 - (void)addDependency:(NSOperation * ...

  4. python 线程之 threading(四)

    python 线程之 threading(三) http://www.cnblogs.com/someoneHan/p/6213100.html中对Event做了简单的介绍. 但是如果线程打算一遍一遍 ...

  5. python 线程之 threading(三)

    python 线程之 threading(一)http://www.cnblogs.com/someoneHan/p/6204640.html python 线程之 threading(二)http: ...

  6. python 线程之_thread

    python 线程之_thread _thread module: 基本用法: def child(tid): print("hello from child",tid) _thr ...

  7. Java多线程之ConcurrentSkipListMap深入分析(转)

    Java多线程之ConcurrentSkipListMap深入分析   一.前言 concurrentHashMap与ConcurrentSkipListMap性能测试 在4线程1.6万数据的条件下, ...

  8. 【C#】线程之Parallel

    在一些常见的编程情形中,使用任务也许能提升性能.为了简化变成,静态类System.Threading.Tasks.Parallel封装了这些常见的情形,它内部使用Task对象. Parallel.Fo ...

  9. iOS多线程之GCD小记

    iOS多线程之GCD小记 iOS多线程方案简介 从各种资料中了解到,iOS中目前有4套多线程的方案,分别是下列4中: 1.Pthreads 这是一套可以在很多操作系统上通用的多线程API,是基于C语言 ...

随机推荐

  1. 内存(MRC)

    一.计数器的基本操作1> retain : +1, 方法返回的是对象本身2> release :-13> retainCount : 获得计数器4> dealloc  * 当一 ...

  2. ASP.NET 连接 SQL Server 和 Oracle 教程

    临近期末,有很多同学都问我怎么关于ASP.NET 连接 SQL Server 和 Oracle 的问题.由于人太多了,我也不能一一去帮忙,就写了这篇博客.希望对大家有用处. 首先,前期准备是要安装数据 ...

  3. RedMine 版本管理工具

    一.介绍: Redmine 是一个开源的.基于Web的项目管理和缺陷跟踪工具.它用日历和甘特图辅助项目及进度可视化显示.同时它又支持多项目管理.Redmine是一个自由开放 源码软件解决方案,它提供集 ...

  4. ViewPager实现页卡的最新方法--简洁的TabLayout(谷歌支持包)

    效果图: 添加依赖包: compile ‘com.android.support:design:‘ 布局文件: <?xml version="1.0" encoding=&q ...

  5. idea破解码

    43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiI ...

  6. Android关机流程源码分析

    上一篇文章Android 开关机动画显示源码分析详细介绍了开关机动画的显示过程,Android系统开机时,在启动SurfaceFlinger服务过程中通过Android属性系统方式来启动bootani ...

  7. 11417 - GCD

    Problem A GCD Input: Standard Input Output: Standard Output Given the value of N, you will have to f ...

  8. 灵活运用Zend框架

    $aAwardMem = $this->dao_raward->getAwardAndMem($where,'award_level asc',false,false,false,'awa ...

  9. poj1528---(数论)

    题意:一个数除了自身以外的所有因数相加,得到的数如果小于自身,输出deficient,否则输出abundant,如果相等,输出perfect 这道题核心:求一个数的所有除本身之外的因数的和 ,i; ; ...

  10. iOS禁用部分文件ARC

    TARGETS的build Phases中的Compile Source里修改文件备注文件参数设定: 增加-fobjc-arc来使单个文件 支持ARC,或者添加-fno-objc-arc使单个文件不支 ...