进程
进程是什么?
进程:执行中的程序。包括代码段、程序计数器、堆栈段(临时数据,如局部变量、函数参数和返回地址)、堆(进程运行期间动态分配的内存)、进程状态、CPU 调度信息、I/O状态信息(如打开文件列表)
进程控制块(Process Control Block)
(详见《操作系统概念(第 7 版)》 - P73)
线程
线程是什么?
线程是 CPU 使用的基本单元,由线程 ID、程序计数器、寄存器集合和栈组成。
进程与线程的区别?
线程与属于同一进程的其他线程共享代码段、公共数据段、打开文件和信号等等。
(《操作系统概念(第 7 版)》 - P111)
多进程与多线程的区别?
区别 1:和线程不同,进程没有任何共享状态;如果某个进程修改数据,改动只限于那个进程内。
(Python 参考手册 - P336)
区别 2:Python 中的多进程可以实现真正的并行,Python 中的多线程不能实现真正的并行。
(OS概念 - 第 7 版 - P112)
线程优点:
- 资源共享:线程默认共享所属进程的内存、代码、数据等资源;
- 经济:相比于进程,创建、切换线程的时间、资源开销较小;
- 响应度高。
Python 中的多线程?
由于 GIL 的存在,这个锁保证同一时刻只有 1 个线程在运行。
(《Python 核心编程(第 2 版)》 - 18.3.1 全局解释器锁 ( GIL ) - P514)
即使是多核 CPU,使用多线程编程,各个线程也只能交替使用 CPU 。
因此Python 中的多线程并不能实现真正的并行。
(Python 3 教程 - 廖雪峰 - 进程和线程 - 多线程 - 多核 CPU 。)
Python 多进程编程
后台进程
如果 1 个进程是后台进程,那么,当创建这个后台进程的进程终止,后台进程会自动终止。
(Python 参考手册 - P337)
以单个进程的形式创建、启动函数
代码清单 - 1
# p337_single_process_with_function.py
from multiprocessing import Process
from time import ctime, sleep
def clock(interval):
while True:
print("The time is %s" % ctime())
sleep(interval)
if __name__ == "__main__":
p = Process(target=clock, args=(2,))
#p.daemon = False
p.start()
#print("hello!")
#p.join()
代码清单 - 2
# p337_single_process_with_function_Daemon_False.py
from multiprocessing import Process
from time import ctime, sleep
def clock(interval):
while True:
print("The time is %s" % ctime())
sleep(interval)
if __name__ == "__main__":
p = Process(target=clock, args=(2,))
p.daemon = False
p.start()
#print("hello!")
#p.join()
以上两段代码均会永远执行。
补充一点背景知识:
- 主进程的 daemon 标志默认为 False,即主进程默认不是后台进程;
- 在主进程开启的子进程会继承主进程的 daemon 标志,于是子进程的 daemon 标志为 False,子进程默认不是后台进程;
- 如果主进程结束了,后台进程也会随之结束,非后台进程不会随主进程结束而结束。
上面的两段代码的区别仅仅在于是否显式地将进程 p 设置为非后台进程,第 1 段代码虽然未将子进程 p 设置为非后台进程,但是,实际上效果等于第 2 段代码中 p.daemon = False
,将子