一:multiprocessing模块介绍
python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程。Python提供了multiprocessing。
multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似。
multiprocessing模块的功能众多:支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。
需要再次强调的一点是:与线程不同,进程没有任何共享状态,进程修改的数据,改动仅限于该进程内。
multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似。
multiprocessing模块的功能众多:支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。
需要再次强调的一点是:与线程不同,进程没有任何共享状态,进程修改的数据,改动仅限于该进程内。
二:创建子进程的两种方式
方式一:调用开启子进程的类Process实例化
from multiprocessing import Process import time def task(name): print("%s is runnig"%name) time.sleep(3) print("process is done") if __name__ == "__main__":#在windows系统中,如果不在这条语句下面调用的话, # p= Process(target=task,args=("egon",))#元组方式传值 p= Process(target=task,kwargs={"name":"egon"})#关键字方式传值,#实例化一个进程(未启动) p.start()#应用程序给操作系统发送请求,建立新的进程,当请求发送后,语句就执行完毕,往下一步去了 print("=======")
方式二:自定义开启子进程的类(继承Process)
from multiprocessing import Process import time class MyProcess(Process): def __init__(self,name): super(MyProcess,self).__init__() self.name=name def run(self): print('%s is running' %self.name) time.sleep(3) print('%s is done' %self.name) if __name__ == '__main__': p=MyProcess('egon') p.start() print('主')
三:父进程等待子进程
from multiprocessing import Process def task(name): print("%s is runnig"%name) if __name__ == "__main__": # p= Process(target=task,args=("egon",)) for i in range(10): p= Process(target=task,args=(i,)) p.start()#向操作系统发送请求 p.join()#让父进程等待子进程死亡 print("=======")上述程序的执行效果,当一个子进程被操作系统开始创建,然后运行出街结果,在这之前,父程序一直停留在
p.join(),只有子程序执行完了后才会进行下一次的循环,相当于依次执行子程序,串行的效果,
将程序改动下
from multiprocessing import Process def task(name): print("%s is runnig"%name) if __name__ == "__main__": # p= Process(target=task,args=("egon",)) p_list = [] for i in range(10): p= Process(target=task,args=(i,)) p_list.append(p) p.start()#向操作系统发送请求 for p in p_list: p.join()#让父进程等待子进程死亡 print("=======")
这样改动过后,所有的子程序创建请求都已经发送给操作系统,这时候要求在所有的子程序执行结束后才执行父程序的最后一行代码,总共的时间,相当于最花费时间最长的子程序,是程序有了并发执行的效果。
四:进程的其他属性
from multiprocessing import Process import time def task(name): print("%s is runnig"%name) time.sleep(1) print("process is done") if __name__ == "__main__": p= Process(target=task,kwargs={"name":"egon"}) p.start() print(p.pid)#进程p的id print(p.name)#进程p的名字 print(p.terminate())#强制终止进程 p.join() print(p.is_alive())#进程是否存在
五:验证进程之间的物理隔离
from multiprocessing import Process import time x = 1000 def task(name): global x x =0 #修改的是子进程自己的属性x,因为内存的物理隔离,所以子进程的修改不会影响到父进程 print("%s is runnig"%name) time.sleep(1) print("process is done",x)#打印的是子进程的数据 if __name__ == "__main__": # p= Process(target=task,args=("egon",)) p= Process(target=task,kwargs={"name":"egon"}) p.start() p.join()#让父进程等待子进程死亡 print("=======") print(x)#打印的是父进程的属性六:僵尸进程与孤儿进程
僵尸进程:在linux中父进程创建子进程,在子进程执行结束完成后,并不会完全的“死去”,而是会保留一些状态属性供父进程查询,当父进程查询到子进程死去后,会启用自己的回收机制,回收子程序的“尸体”,另外,linux中__init__是所有进程的父进程。
僵尸进程的危害:每一个进程都有一个进程id如果僵尸进程没有被回收的话,会占用进程ID,
孤儿进程:当父进程退出,而子进程仍在运行的时候,这些,子进成没有了父进程监测,就变成了孤儿进程,但是孤儿进程是无害的,因为在孤儿进程出现后,系统主进程init将会接管孤儿进程,成为孤儿进程新的父进程。替代完成父进程的一系列工作。