线程正常终止pthread_exit,pthread_join,pthread_kill,pthread_cancel,sigwait,sigaddset
int pthread_join(pthread_t thread, void **retval);
int pthread_detach(pthread_t thread);
void pthread_exit(void *retval);
线程正常终止的方法:
1、return从线程函数返回。
2、通过调用函数pthread_exit使线程退出
3. 线程可以被同一进程中的其他线程取消。
主线程、子线程调用exit, pthread_exit,互相产生的影响。
1、在主线程中,在main函数中return了或是调用了exit函数,则主线程退出,且整个进程也会终止,
此时进程中的所有线程也将终止。因此要避免main函数过早结束。
2、在主线程中调用pthread_exit, 则仅仅是主线程结束,进程不会结束,进程内的其他线程也不会结束,
知道所有线程结束,进程才会终止。
3、在任何一个线程中调用exit函数都会导致进程结束。进程一旦结束,那么进程中的所有线程都将结束。
为什么要使用pthread_join?
线程终止最重要的问题是资源释放的问题。
线程终止时需要注意线程同步的问题。一般情况下,进程中各个线程的运行是相互独立的,线程的终止不会相互通知,也不会影响其他线程,
终止的线程所占用的资源不会随着线程的结束而归还系统,而是仍为线程所在的进程持有。在Linux中,默认情况下是在一个线程被创建后,
必须使用此函数对创建的线程进行资源回收,但是可以设置Threads attributes来设置当一个线程结束时,直接回收此线程所占用的系统资源,详细资料查看Threads attributes。
函数pthread_join用来等待一个线程的结束,pthread_join的调用者将被挂起并等待thread线程终止。需要注意的是一个线程仅允许一个线程使用pthread_join
等待它结束,并且被等待的线程应该处于可join状态。即非DETACHED状态。DETACHED是指某个线程执行pthread_detach后所处的状态。处于DETACHED状态
的线程无法由pthread_join同步。
一个可pthread_join的线程所占用的资源仅当有线程对其执行了pthread_join后才会释放,因此为了防止内存泄漏,所有线程终止时,要么已经被设置为DETACHED状态
要么使用pthread_join来回收资源。
notice:
一个线程不能被多个线程等待。否则第一个收到信号的线程成功返回。其余调用pthread_join的线程返回错误码
ESRCH No thread with the ID thread could be found.
示例代码:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h> void* thread_func(void* arg)
{
printf("thread:%lu is running\n", pthread_self());
int rv = ;
pthread_exit((void*)rv);
} int main()
{
pthread_t thid;
int rv; pthread_create(&thid, NULL, thread_func, NULL); printf("main thread begin join\n");
pthread_join(thid, (void*)&rv);
printf("main thread end join\n");
printf("the thread:%lu exit:%d\n", thid, rv); return ;
}
----------------------------------------------------------------------------
将线程的属性称为detached,则线程退出时会自己清理资源。
void*start_run(void*arg){//dosomework}intmain(){ pthread_t thread_id; pthread_attr_ tattr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_create(&thread_id, &attr, start_run, NULL); pthread_attr_destroy( &attr ); sleep(5); exit(0);}线程可以通过自身执行结束来结束,也可以通过调用pthread_exit()来结束线程的执行。另外,线程甲可以被线程乙被动结束。这个通过调用pthread_cancel()来达到目的。
当然,线程也不是被动的被别人结束。它可以通过设置自身的属性来决定如何结束,线程的被动结束分为两种,一种是异步终结,另外一种是同步终结。异步终结就是当其他线程调用pthread_cancel的时候,
线程就立刻被结束。而同 步终结则不会立刻终结,它会继续运行,直到到达下一个结束点(cancellation point)。当一个线程被按照默认的创建方式创建,那么它的属性是同步终结。
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 否则有可能会出现“段错误”的异常!
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
-----------------------------------------------------------------------------------------
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<pthread.h>
#include<time.h> pthread_t tid;
sigset_t set; void myfunc()
{
printf("hello\n:");
} void* mythread(void* p)
{
int signum;
while()
{
sigwait(&set, &signum); if (SIGUSR1 == signum)
{
myfunc();
}
else if (SIGUSR2 == signum)
{
printf("I will sleep 2 seconds and exit\n");
sleep();
break;
}
}
} int main()
{
char tmp;
void *status;
sigemptyset(&set);
sigaddset(&set,SIGUSR1);
sigaddset(&set,SIGUSR2);
sigprocmask(SIG_SETMASK,&set,NULL);
pthread_create(&tid,NULL,mythread,NULL); printf(":");
while()
{
char* p = NULL;
char str[]; scanf("%c",&tmp);
p = gets(str); //printf("get %c\n", tmp);
if('a'==tmp)
{
pthread_kill(tid,SIGUSR1);//发送SIGUSR1,打印字符串。
sleep();
}
else if('q'==tmp)
{
//发出SIGUSR2信号,让线程退出,如果发送SIGKILL,线程将直接退出。
pthread_kill(tid,SIGUSR2);
//等待线程tid执行完毕,这里阻塞。
pthread_join(tid,&status);
printf("finish\n");
break;
}
else
{
printf(":");
} }
return ;
}
线程正常终止pthread_exit,pthread_join,pthread_kill,pthread_cancel,sigwait,sigaddset的更多相关文章
- 线程相关函数(1)-pthread_create(), pthread_join(), pthread_exit(), pthread_cancel() 创建取消线程
一. pthread_create() #include <pthread.h> int pthread_create(pthread_t *thread, const pthread_a ...
- pthread_exit pthread_join
int pthread_join(pthread_t thread, void **retval); int pthread_detach(pthread_t thread); void pthrea ...
- java 线程的终止与线程中断
关于线程终止: 1.一般来讲线程在执行完毕后就会进入死亡状态,那该线程自然就终止了. 2.一些服务端的程序,可能在业务上需要,常驻系统.它本身是一个无穷的循环,用于提供服务.那对于这种线程我们该如何结 ...
- Delphi线程的终止
当线程对象的Execute()执行完毕,我们就认为此线程终止了.这时候,它会调用Delphi的一个标准例程EndThread(),这个例程再调用API函数ExitThread().由ExitThrea ...
- 并发基础(九) java线程的终止与中断
1.简单了解一下:为何不赞成使用 Thread.stop.Thread.suspend 和 Thread.resume? suspend .resume.stop方法分别完成了线程的暂停.恢复.终 ...
- Java 线程的终止-interrupt
Java线程的终止——interrupt 取消/关闭的场景 我们知道,通过线程的start方法启动一个线程后,线程开始执行run方法,run方法运行结束后线程退出,那为什么还需要结束一个线程呢?有多种 ...
- 线程pthread_create()、pthread_exit()、pthread_join()、pthread_cancel()
- 多线程:pthread_exit,pthread_join,pthread_self
/*exit_join_id.c*/ #include<pthread.h> #include<stdio.h> void* eji(void* agr) { printf(& ...
- Tomcat热部署,Web工程中线程没有终止
近期项目中,用 jenkins 热部署 web工程时,发现工程中静态持有的线程(将ScheduledExecutorService定时任务存储在静态Map中),导致不定时出现数据库访问事务关闭异常,如 ...
随机推荐
- 20145307陈俊达_安卓逆向分析_APKtools分析smail
20145307陈俊达_安卓逆向分析_APKtools分析smail 引言 真刺激呢!到了第二篇博客了,难度开始加大,之前是简单的dex2jar和有图形界面的jd-gui,现在来隆重介绍强大的反汇编工 ...
- 20145322 Exp5 MS08_067漏洞测试
20145322何志威 Exp5 MS08_067漏洞测试 实验过程 kali ip:172.20.10.4 windows 2003 ip:172.20.10.2 在控制台内使用search ms0 ...
- 20165310_Exp2实验二《Java面向对象程序设计》
实验二<Java面向对象程序设计> TDD与单元测试 前期准备: 什么是单元测试? 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证.对于单元测试中单元的含 ...
- 20165211 预备作业3 Linux安装与学习
20165211 预备作业3 Linux安装与学习 1. Linux安装 涉及软件:VirtualBox,Ubuntu 参考教程:基于VirtualBox安装Ubuntu图文教程 安装过程的问题 在安 ...
- 20165211 2017-2018-2 《Java程序设计》第7周学习总结
20165211 2017-2018-2 <Java程序设计>第7周学习总结 教材学习内容总结 本周,我学习了书本上第十一章的内容,以下是我整理的主要知识. 第十一章 JDBC和MySQL ...
- updateByPrimaryKeySelective更新失败
问题:使用Mybatis中Mapper内置方法updateByPrimaryKeySelective更新失败. 发现:控制台打印出来的sql语句发现where条件出现所有属性. 解决:映射的实体类没有 ...
- Serv-U FTP服务器安装及使用图解教程
Serv-U,是一种被广泛运用的FTP服务器端软件,支持3x/9x/ME/NT/2K等全Windows系列.可以设定多个FTP服务器.限定登录用户的权限.登录主目录及空间大小等,功能非常完备. 它具有 ...
- TeeChart的坐标轴
TeeChart一共有六个坐标轴,一下是默认值 tChart1.Axes.Bottom.Visible = true;//横轴 tChart1.Axes.Left.Visible = true;//纵 ...
- 【第六章】 springboot + 事务
在实际开发中,其实很少会用到事务,一般情况下事务用的比较多的是在金钱计算方面. mybatis与spring集成后,其事务该怎么做?其实很简单,直接在上一节代码的基础上在相应的方法(通常是servic ...
- BZOJ4419: [Shoi2013]发微博 暴力
Description 刚开通的SH微博共有n个用户(1..n标号),在短短一个月的时间内,用户们活动频繁,共有m条按时间顺序的记录: ! x 表示用户x发了一条微博: + x y 表示用户x和用 ...