进程、线程的概念以及多线程编程的基础知识请参考文末给出的方式在公众号历史文章中查找相关文章进行阅读。本文重点介绍线程对象daemon属性在线程退出时产生的作用和影响。
首先,我们来看一下官方文档对守护线程(daemon thread)的描述:
再来看一下官方文档对线程对象daemon属性的描述:
可知:
1)主线程不是守护线程,daemon属性的值为False;
2)新线程被创建时会继承父线程daemon属性的值;
3)主线程创建的所有子线程都默认daemon=False,如果要修改子线程daemon属性值,必须在调用start()方法启动线程之前进行;
4)主线程退出时会检查是否有daemon=False的子线程,如果有则延迟退出;如果当前所有子线程的daemon都是True,则主线程直接退出,同时所有daemon=True的子线程都会被强制结束;
5)所有daemon=True的子线程有可能遭遇被强制退出,其中的资源可能无法正确释放,从而有可能(但不一定)引发异常;
6)主线程结束也就意味着整个程序退出,进程结束。
以下面的代码为例,主线程创建并启动两个子线程之后,直接退出,两个daemon=True的子线程也被迫结束,但这时子线程可能正在向标准输出控制台输出内容,而当前进程已结束导致标准输出控制台被释放,子线程无法取得访问权限,从而引发异常,尽管每次引发异常的时机和位置并不一样。
运行状态如下图所示:
修改代码,在程序最后增加一句sleep(1),也就是主线程创建并启动两个daemon=True的子线程之后,等待一秒钟再退出,此时由于两个子线程都已输出完要输出的内容并进入sleep状态不再使用标准输出控制台的资源,所以子线程被强制结束时没有引发异常。
连续多次运行结果如下图所示,虽然结果仍不可再现(这样的结果对于没有使用同步机制的多线程程序是正常的),但没有抛出异常:
那么,如果调整子线程代码,使得先等待一段时间,在主线程退出时子线程还没有开始输出,结果会怎样呢?如下图所示,右边是调整后的代码,左侧是运行结果,主线程创建并启动两个线程之后等待一秒钟退出,此时两个子线程并没有尝试占用标准输出控制台的资源,被强制退出时没有引发异常。
再例如,下面的代码,主线程退出时强行结束两个子线程,子线程中申请的文件对象没有正确释放,文件中最终写入的内容不确定。
公众号“Python小屋”
标签:输出,daemon,Python,主线,线程,退出,True From: https://blog.51cto.com/u_9653244/6454786