第三十六天 守护进程 互斥锁 进程间通讯

时间:2022-07-26 20:29:00

一.昨日回顾

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))