进程与子进程补漏及守护进程与互斥锁的概念
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()
越是困难的事越要立即去做,这样收益才会最大!!!