进程会变成一个僵尸进程
主进程的结束逻辑:
- 主进程的代码结束,等待所有的子进程结束,给子进程回收资源,主进程结束。
主进程怎么知道子进程结束了的呢? —— 基于网络、文件
4.join方法
join方法:同步阻塞,直到子进程结束就结束
把一个进程的结束事件封装成一个join方法
执行join方法的效果:就是 阻塞,直到这个子进程执行结束就结束阻塞。
# 开起一个子进程
import time
from multiprocessing import Process
def send_mail():
time.sleep(3)
print('发送了一封邮件')
if __name__ == '__main__':
p = Process(target=send_mail)
p.start() # 异步 非阻塞
# time.sleep(5)
print('join start')
p.join() # 同步 阻塞,直到p对应的进程结束之后才结束阻塞
print('5000封邮件已发送完毕')
# 开起多个子进程
# 开启10个进程,给公司的5000个人发邮件,发送完邮件之后,打印一个消息“5000封邮件已发送完毕”
import time
import random
from multiprocessing import Process
def send_mail(a):
time.sleep(random.random())
print('发送了一封邮件',a)
if __name__ == '__main__':
l = []
for i in range(10):
p = Process(target=send_mail,args=(i,))
p.start()
l.append(p)
print(l)
for p in l:p.join()
# 阻塞 直到上面的十个进程都结束
print('5000封邮件已发送完毕') # 所有的子进程都结束之后要执行的代码写在这里
7. 守护进程
1.有一个参数可以把一个子进程设置为一个守护进程
import time
from multiprocessing import Process
def son1(a,b):
while True:
print('is alive')
time.sleep(0.5)
def son2():
for i in range(5):
print('in son2')
time.sleep(1)
if __name__ == '__main__':
p = Process(target=son1,args=(1,2))
p.daemon = True
p.start() # 把p子进程设置成了一个守护进程
p2 = Process(target=son2)
p2.start()
time.sleep(2) # son1只执行了2S
守护进程是随着主进程的代码结束而结束的
应用场景:
所有的子进程都必须在主进程结束之前结束,由主进程来负责回收资源
p.is_alive() 判断一个子进程是否还活着
p.terminate() 强制结束一个子进程
import time
from multiprocessing import Process
def son1():
while True:
print('is alive')
time.sleep(0.5)
if __name__ == '__main__':
p = Process(target=son1)
p.start() # 异步 非阻塞
print(p.is_alive())
time.sleep(1)
p.terminate() # 异步的 非阻塞
print(p.is_alive()) # 进程还活着 因为操作系统还没来得及关闭进程
time.sleep(0.01)
print(p.is_alive()) # 操作系统已经响应了我们要关闭进程的需求,再去检测的时候,得到的结果是进程已经结束了
什么是异步非阻塞?—— terminate
2.Process类使用面向对象的方式:
def start(self) ——> None :……开起了一个子进程,调用run。
def run(self) ——> None :……
import os
import time
from multiprocessing import Process
class MyProcecss1(Process):
def __init__(self,x,y): # 传参数,不要忘记写init方法
self.x = x
self.y = y
super().__init__()
def run(self): # 子进程中要做的事情写在run方法中
print(self.x,self.y,os.getpid())
while True:
print('is alive')
time.sleep(0.5)
class MyProcecss2(Process):
def run(self):
for i in range(5):
print('in son2')
time.sleep(1)
if __name__ == '__main__':
mp = MyProcecss1(1,2)
mp.daemon = True
mp.start()
print(mp.is_alive())
mp.terminate()
mp2 = MyProcecss2()
mp2.start()
print('main :',os.getpid())
time.sleep(1)
Process类的总结:
1.开启进程的方式
1.面向函数:
def 函数名:要在子进程中执行的代码
p = Process(target= 函数名,args=(参数1,))
2.面向对象:
class 类名(Process):
def init(self,参数1,参数2): # 如果子进程不需要参数可以不写
self.a = 参数1
self.b = 参数2
super().__init__()
def run(self): # 要在子进程中执行的代码
p = 类名(参数1,参数2)
2.Process提供的操作进程的方法
- p.start() 开启进程 异步非阻塞
- p.terminate() 结束进程 异步非阻塞
- p.join() 同步阻塞
- p.isalive() 获取当前进程的状态
- daemon = True 设置为守护进程,守护进程永远在主进程的代码结束之后自动结束
8. 锁
并发 能够做的事儿,如:
[TOC]
- 1.实现能够响应多个client端的server
- 2.抢票系统
1.如果在一个并发的场景下,涉及到某部分内容,是需要修改一些所有进程共享的数据资源,需要加锁来维护数据的安全。
2.在数据安全的基础上,才考虑效率问题
3.同步存在的意义:数据的安全性
在主进程中实例化 lock = Lock(),把这把锁传递给子进程,在子进程中,对需要加锁的代码 进行 with lock:
- with lock相当于lock.acquire()和lock.release()
import time
import json
from multiprocessing import Process,Lock
def search_ticket(user):
with open('ticket_count') as f:
d