并发编程多进程Process2 获取pid 僵尸进程和孤儿进程 守护进程 对象.join() is_alive() terminate 模拟抢票小程序
当前进程的角度
os.getpid() 获取当前进程的pid
os.getppid() #获取当前进程的父进程的pid
子进程对象.pid #获取当前进程的子进程pid
僵尸进程和孤儿进程
僵尸进程(有害):在exit()后仍然还有pid,并没有马上就消失掉,等待父进程处理
如果有大量僵尸进程,将会仅为没有进程号而导致系统不能产生新的进程,应当避免这种进程的危害
孤儿进程(无害):父进程退出 一个或者多个子进程还在运行,并由init进程对他们完成状态的处理
init进程会处理他的一切善后工作。
守护进程
-
主进程闯进守护进程
- 守护进程会在主进程代码执行结束后就终止。
- 守护进程内无法再开启子进程,否则抛出异常。
-
进程之间是互相独立的,主进程代码运行结束,守护进程就停止
-
def task(x): print(f'{x} start') time.sleep(2) print(f'{x} end') if __name__ == '__main__': p=Process(target=task,args=('sb',)) p.daemon = True ##一定要在p.start()前设置,设置p为守护进程,禁止p创建子进程,并且父进程代码执行结束,p即终止运行 p.start() print('主')
对象.join()
是向操作系统发送请求,然后告知操作系统p的id号不需要再被占用了,回收就可以
但是会留一个pid,僵尸进程
from multiprocessing import Process
import time,os
def task():
print('%s is running' %os.getpid())
time.sleep(3)
if __name__ == '__main__':
p=Process(target=task)
p.start()
p.join() # 等待进程p结束后,join函数内部会发送系统调用wait,去告诉操作系统回收掉进程p的id号
print(p.pid) #此时能看到子进程p的id号
print('主')
is_alive()
判断进程是否为已经运行完
terminate
直接终止进程的运行
模拟抢票小程序
多个进程共享一个文件
文件当数据库,模拟抢票
from multiprocessing import Process
import json,time,os
def search():
time.sleep(1) # 模拟网络io
with open('db.txt',mode='rt',encoding='utf-8') as f:
res = json.load(f)
print(f'还剩{res["count"]}')
def get():
with open('db.txt',mode='rt',encoding='utf-8') as f:
res = json.load(f)
# print(f'还剩{res["count"]}')
# time.sleep(1) # 模拟网络io
if res['count'] > 0:
res['count'] -= 1
with open('db.txt',mode='wt',encoding='utf-8') as f:
json.dump(res,f)
print(f'进程{os.getpid()} 抢票成功')
time.sleep(1.5) # 模 拟网络io
else:
print('票已经售空啦!!!!!!!!!!!')
def task():
search()
get()
if __name__ == '__main__':
for i in range(15):
p = Process(target=task)
p.start()
# p.join()
# 为了保证数据的安全,要牺牲掉效率.