一.昨日回顾
1. 进程 相关概念
并发 看起来像是同时运行的中 本质是不停切换执行 多个进程随机执行
并行 同一时刻 多个进程 同时进行 只有多喝处理器才有真正的并行
串行 一个一个 依次排队执行
阻塞 遇到了I/O操作 看起来就是代码卡住了
非阻塞 不会卡住代码的执行
阻塞 和 非阻塞 说的是同一个进程的情况下
同步 一个调用必须获得返回结果才能继续执行
异步 一个调用发起后 发起反不需要等待他的返回值
同步和异步 必须存在多个进程(线程)
无论是进程还是线程都是两条独立执行的路径
2.如何使用多进程
P= Process(taget=一个函数,args=(函数的参数))
p.start()让操作系统启动这个进程
3.多进程的执行顺序
主进程必须先执行
子进程应该在主进程后执行
一旦子进程启动了 后续的顺序就无法控制了
二.今日内容
1.守护进程
守护 就是看着 陪着
在代码中 进程只能由进程类守护
一个进程守护着另一个进程 指的是两个进程之间的关联关系
特点:守护进程(妃子)在守护进程(皇帝)死亡时 会跟随被守护进程死亡
守护进程能不能先死?
2.互斥锁
3.IPC
4.生产者消费者模型
三.守护进程
from multiprocessing import Process
impot time
def task():
print("福晋 升级为皇后")
time.sleep(3)
print("皇后陪葬")
if __name__=='__main__':
p = Process(targe=task)
# 将这个子进程设置为当前进程守护进程
p.daemon
p.start()
p.start()
print("崇祯登基")
print("崇祯驾崩了")
# 守护者进程的代码非常简单
p.daemon = True
注意必须在启动进程之前执行
什么时候需要使用守护进程
例如:qq中有个下载视频 应该用子进程去做 但是 下载的过程种 qq退出 那么下载也没必要继续了
使用场景不多 了解即可
四.互斥锁
from multiprocessing import Process,Lock #进程间 内存空间是相互独立的 def task(lock): lock.acquire() for i in range(1000): print("===") lock.release() def task2(lock): lock.acquire() for I in range(1000): print("=====") def task3(lock): lock.acquire() for i in rang(1000): print("=====") lock.release() if __name__='__main__': mute = Lock() p1 = Process(target=task1,args=(mutex,)) p2 = Process(target=task2,args=(mutex,)) p3 = Process(target=task3,args=(mutex,)) p1.start() p2.start() p3.start() print("over!")
抢票系统
抢票---多个用户在同时读写一个数据
from multiprocessing import Process,Lock import json,time,random def show_ticket(name): time.sleep(random.randint(1,3)) with open(r"ticket.json","rt",encoding="utf-8")as f: dic = json.load(f) print("%s查看 剩余票数:%s"%(name,dic["count"])) # 购买票 def buy_ticket(name): with open(r"ticket.json","rt",encoding="utf-8")as f: #修改数据 dic = json.load(f) if dic["count"] > 0: time.sleep(random.randint(1,3)) with open(r"ticket.json","wt",encoding="utf-8")as f2: json.dump(dic,f2) print("%s 购票成功!"%name) def task(lock,name): show_ticket(name) lock.acquire() buy_ticket(name) lock.release() if __name__=='__main__': mutex =Lock() for i in range(11): p = Process(target=task,args=(mutex,"客户%s"%i)) p.start()
五.进程间通讯
IPC 指的是进程间通讯
之所以开启紫金财产 肯定需要他帮我们完成任务 很多情况下 需要将数据返回给父进程
然而,进程内存是物理隔离的
解决方案:
1.将共享数据放到文件中 就是慢
2.管道 subprocess中那个 管道只能单向通讯 必须存在父子关系
3.共享一块内存区域 得操作系统帮你分配 速度快
from multiprocessing import Process,Manager import time def task(dic): print("子进程xxxxxx") dic["name"] = "xx" if __name__'__main__': m =Manager() dic = m.dict({}) p = Process(target=task,args=(dic,)) p.start() time.sleep(3) print(dic)
进程间通讯的另一种方式 使用 queue
queue 队列
队列的特点:
先进先出
后进后出
就像扶梯
from multiprocessing import Process,Queue # 阻塞操作 必须掌握 q = Queue(3) # # 存入数据 q.put("hello",block=False) q.put(["1","2","3"],block=False) q.put(1,block=False) # 当容量满的时候 再执行put 默认会阻塞直到执行力了get为止 # 如果修改block=False 直接报错 因为没地方放了 # q.put({},block=False) # # # 取出数据 print(q.get(block=False)) print(q.get(block=False)) print(q.get(block=False)) # 对于get 当队列中中没有数据时默认是阻塞的 直达执行了put # 如果修改block=False 直接报错 因为没数据可取了 print(q.get(block=False))