1.上节课补漏
把原来在父进程中串行的任务分配到子进程中,实现并发。
看下上节课复习例题
子进程方式二的run()固定的
进程id号是一个进程在操作系统里的身份证号
僵尸进程:占据pid未回收,其他系统资源回收了
join()里面有wait 等到子进程执行完毕,将子进程占用操作系统的pid回收
开启一个子进程时会给他一个pid,回收的是操作系统所占的pid号,而不是子进程属性里的pid,子进程结束后依然可以查看他的pid。
from multiprocessing import Process import time import os def task(): print('%s is running' %os.getpid()) time.sleep(3) print('%s is done' % os.getpid()) if __name__ == "__main__": p=Process(target=task) p.start() # 仅仅只是向操作系统发送一个开启进程的信号 print(p.pid) p.join() # 等到子进程p执行完毕后,将p占用的操作系统的pid回收 time.sleep(2) print(p.pid) # 依然可以查看他的pid 回收的是他在操作系统所占的pid号 他自己属性里也有 print('主')
僵尸进程目的:为了让父进程随时可以拿到子进程pid。
出现大量僵尸进程处理:直接杀死父进程
谁开了谁就是他的父进程:比如cmd运行一个py文件 cmd就是父进程
杀死父进程cmd,父进程cmd并未关闭窗口是因为cmd被当作终端在输出,如何关闭?
2.守护进程
一定要放在p.start()之前
守护进程其实就是一个“子进程”,
守护=》伴随
守护进程会伴随主进程的代码运行完毕而死掉。
为何要用守护进程?
守护:该子进程内的代码在父进程代码运行完毕后就没有存在意义了,就应该将该进程设置为守护进程,会在父进程代码结束后死掉。
进程:当主进程需要把任务并发出去执行,需要把该任务放到一个子进程里。
子进程·daemon = True 表示该进程未守护进程,这段代码一定要放在start之前
from multiprocessing import Process import time,os def task(name): print('%s is running' %name) time.sleep(3) if __name__ == '__main__': p1=Process(target=task,args=('守护进程',)) p2=Process(target=task,args=('正常的子进程',)) p1.daemon = True # 一定要放到p.start()之前 p1.start() p2.start() print('主')
注意:守护进程结束的时间是主进程最后一行代码完全执行完毕,如果有输出就是最后一个字符打印到终端才算结束。
计算机性能越好,开启子进程速度越快,输出可能就不一样,详情见下面的代码。
#主进程代码运行完毕,守护进程就会结束 from multiprocessing import Process import time def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(3) print("end456") if __name__ == '__main__': p1=Process(target=foo) p2=Process(target=bar) p1.daemon=True p1.start() p2.start() print("main-------") ''' main------- 456 enn456 ''' ''' main------- 123 456 enn456 ''' ''' 123 main------- 456 end456 '''
3.进程的互斥锁
mutex 互斥的意思 mutex = Lock()
文件是进程可以共享的
原理:将并发变成串行,保证数据安全
互斥锁不能连续acquire,只能release再acquire
join才是真正的串行
互斥锁是谁优先抢到锁谁执行共享数据代码,其他部分该并发还是并发。
互斥锁:可以将要执行部分的任务代码(只涉及到修改共享数据的代码)变成串行。
join:是要执行任务的所有代码串行。
mutex.acquire()
需要串行的程序
mutex.release()
被锁起来的程序只能一个个进入。
#互斥锁:可以将要执行任务的部分代码(只涉及到修改共享数据的代码)变成串行 #join:是要执行任务的所有代码整体串行 from multiprocessing import Process,Lock # 需要导入互斥锁对应的类 import json import os import time import random # 模拟抢票的流程:查看票和购买票 def check(): time.sleep(1) # 模拟网路延迟 with open('db.txt','rt',encoding='utf-8') as f: dic=json.load(f) print('%s 查看到剩余票数 [%s]' %(os.getpid(),dic['count'])) def get(): with open('db.txt','rt',encoding='utf-8') as f: dic=json.load(f) time.sleep(2) if dic['count'] > 0: # 有票 dic['count']-=1 time.sleep(random.randint(1,3)) with open('db.txt','wt',encoding='utf-8') as f: json.dump(dic,f) print('%s 购票成功' %os.getpid()) else: print('%s 没有余票' %os.getpid()) def task(mutex): # 查票 check() #购票 mutex.acquire() # 互斥锁不能连续的acquire(获得),必须是release以后才能重新acquire get() mutex.release() # with mutex: # 可以用这种表达方式,自动释放 # get() if __name__ == '__main__': mutex=Lock() for i in range(10): p=Process(target=task,args=(mutex,)) p.start() # p.join()