本文共 1731 字,大约阅读时间需要 5 分钟。
在博主的上一篇博客中讲述了线程的基本概念及线程创建,没有看过的小伙伴可以点击这里:
本篇博文将重点从两个方面:线程控制(线程等待、线程终止)及线程属性来进一步分析线程特点。
首先,我们需要知道线程终止的几种方式:
1.从线程函数中return(特殊:从main函数中return,代表进程退出,也代表主线程退出。那么此时线程必定被终止。)
2.直接调用pthread_exit函数终止线程(注意:在线程内调用exit终止的是进程而非线程) 3.调用pthread_cancel函数来取消线程,从而终止线程。与线程终止有关的函数:
下面我们来编写代码实现线程终止。
用pthread_exit函数终止线程
运行结果: 用命令查看,该进程是单进程。用pthread_cancel函数取消线程
从主线程中取消新线程:
执行结果:线程自己取消自己:
执行结果:对于线程等待,我们需要知道以下几点:
1.线程一旦出错,必须由进程承担后果。对于线程,我们只关心它的两种运行情况:
代码跑完了,结果正确 代码跑完了,结果不正确 如果代码都没跑完,中途退出。这意味着进程也会退出,所以就无法查看其退出原因。 2.线程出错,导致进程退出。则属于该进程的其他线程也会退出,因为线程的资源由进程分配。所以一般多进程比多线程的程序稳定。因为多线程程序的不稳定性, 如果一个线程结束运行但没有被join,则它的状态类似于进程中的僵尸进程, 即还有一部分资源没有被回收,导致内存泄漏。
所以创建线程者应该调⽤pthread_join来等待线程运行结束,并可得到线程的退出码来回收其资源。线程等待函数:pthread_join
表达式:调⽤用该函数的线程将挂起等待,直到id为thread的线程终止。
若thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,总结如下:
下面我们来编写程序实现进程等待。
为了对比方便,将上述retval返回值的所有可能情况汇总在一起:
得到如下结果:
至此,线程控制结束。
总的来说,在任何一个时间点上。线程有两种属性:
1.可结合(joinable)属性:线程的默认属性。能够被其他线程收回其资源和杀死,在被其他线程回收之前,它的存储器资源 (例如栈)是不释放的。
2.分离(detached)属性:不能被其他线程回收或杀死,它的存储器资源在它终止时由系统⾃自动释放。注:为了避免存储器泄漏,每个可结合线程都应该要么被显示地回收,即调用pthread_join;要么通过调用pthread_detach函数被分离。
线程分离函数pthread_detach
下面通过代码实现线程分离:
因为线程分离后就不能再被等待,所以在程序中加入等待函数,如果线程分离成功,就会打印出错信息。
运行结果如下:
等待函数打印出错信息,线程分离成功
由于调用pthread_join后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此。
例如,在Web服务器中当主线程为每个新来的连接请求创建⼀个子线程进行处理的时候,主线程并不希望因为调用pthread_join⽽而阻塞(因为还要继续处理之后到来的连接请求)。这时可以在子线程中加入代码 pthread_detach(pthread_self()) 或者主线程调用pthread_detach(thread_id)(非阻塞,可立即返回) 。
将子线程的状态设置为分离的(detached),如此一来,该线程运行结束后会自动释放所有资源。