守护进程,互斥锁,IPC进程间通信,生产者消费者模型

守护进程
'''
1、守护进程
守护进程其实就是一个“子进程”
守护=》伴随
守护进程会伴随主进程的代码运行完毕后而死掉

2、为何用守护进程
关键字就两个:
进程:
当父进程需要将一个任务并发出去执行,需要将该任务放到一个子进程里
守护:
当该子进程内的代码在父进程代码运行完毕后就没有存在的意义了,就应该
将该子进程设置为守护进程,会在父进程代码结束后死掉
'''

from multiprocessing import Process
import time
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-------")
主进程代码运行完毕,守护进程就会结束

互斥锁
#互斥锁:可以将要执行任务的部分代码(只涉及到修改共享数据的代码)变成串行
#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"]))
    #显示哪个id看到的票数

def get():
    with open("db.txt","rt",encoding="utf-8") as f:
        dic = json.load(f)
    time.sleep(random.randint(1,3))
    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)#以json模块进行存储
        print("%s 购票成功" %os.getpid())
    else:
        print("%s 没有余票" %os.getpid())

def task(mutex):
    #查票
    check()
    #购票
    mutex.acquire()#互斥锁不能连续锁acquire(获得上锁),必须是release(放解锁)以后
    # 才能重新acquire,锁需要在想要上锁的函数正上方输入mutex.acquire(),然后再想要
    # 解锁的位置输入mutex.release()
    # 简洁写法再函数上方with mutex:
    # with mutex:
    #     get()#只锁了get,其他并没有锁
    # check()#购票后的查看都是随机时间查看,没有规定必须谁先出来谁可以查看
    # check()
    # check()
    get()
    mutex.release()
if __name__ == '__main__':
    mutex = Lock()#互斥锁要在main下方
    for i in range(10):
        p=Process(target = task,args = (mutex,))
        p.start()
互斥锁

IPC进程间通信,两种方式
IPC:进程间通信,有两种实现方式
1、pipe:
2、queue:pipe+锁

# q=Queue(3)#设置队列最大存放数,先进先出
# #注意:
# #1、队列占用的是内存空间
# #2、不应该往队列中放大数据,应该只存放数据量较小的信息
# #掌握的
# q.put('first')
# q.put({'k':'sencond'})
# q.put(['third',])
# #当超过队列最大存放数时会堵塞,默认会进入等待,等待前面的被取走,然后再进
# q.put(4)
#
# print(q.get())
# print(q.get())
# print(q.get())
# #超过队列最大取出数时会堵塞,默认会进入等待,等待前面有新放入,然后取出
# print(q.get())
# print(q.get(block=True,timeout=4))
# q=Queue(3)
# q.put('first')
# q.put({'k':'sencond'})
# q.put(['third',])
# #默认的block为True,如果将block改为False,造成队列堵塞时会直接报错,
# # 如果block为True,timeout为计时秒数,超过等待秒数会报错
# q.put(4,block=True,timeout=3)
#
# print(q.get())
# print(q.get())
# print(q.get())



q=Queue(3)
q.put('first')
q.put({'k':'sencond'})
q.put(['third',])

print(q.get())
print(q.get())
print(q.get())
#默认的block为True,如果将block改为False,队列中没东西取出会自动报错,
# 如果block为True,timeout为计时秒数,超过等待秒数会报错
print(q.get(block=True,timeout=None))
了解

生产者消费者模型:
'''
1 什么是生产者消费者模型
生产者:比喻的是程序中负责产生数据的任务
消费者:比喻的是程序中负责处理数据的任务

生产者->共享的介质(队列)<-消费者

2 为何用
实现了生产者与消费者的解耦和,生产者可以不停地生产,消费者也可以不停地消费
从而平衡了生产者的生产能力与消费者消费能力,提升了程序整体运行的效率

什么时候用?
当我们的程序中存在明显的两类任务,一类负责产生数据,另外一类负责处理数据
此时就应该考虑使用生产者消费者模型来提升程序的效率

'''

from multiprocessing import Queue,Process
import time,os,random
def producer(q):
    for i in range(10):#循环每次的数值
        res="包子%s" %i
        time.sleep(random.randint(1,3))
        q.put(res)#将制作好的东西放入到队列中
        print("%s 生产了%s" %(os.getpid(),res))
    q.put(None)

def consumer(q):
    while True:
        res=q.get()#循环从队列中取出内容
        if res is None:break
        time.sleep(random.randint(1,3))
        print("%s 吃了 %s" %(os.getpid(),res))

if __name__ == '__main__':
    q=Queue()
    p1=Process(target=producer,args=(q,))
    c1=Process(target=consumer,args=(q,))
    p1.start()
    c1.start()
    print("")
方式一
from multiprocessing import Queue,Process
import time,random,os
def produce(name,food,q):
    for i in range(3):
        res = "%s %s" %(food,i)
        time.sleep(random.randint(1,3))
        q.put(res)
        print("%s 生产了 %s" %(name,food))

def consumer(name,q):
    while True:
        res = q.get()
        if res is None:break
        time.sleep(random.randint(1,3))
        print("%s 吃了 %s" %(name,res))

if __name__ == '__main__':
    q=Queue()
    p1 = Process(target=produce,args=("egon","包子",q))
    p2 = Process(target=produce,args=("hm","汉堡",q))
    p3 = Process(target=produce,args=("张飞","鹿腿",q))

    c1 = Process(target=consumer,args=("fxc",q))
    c2 = Process(target=consumer,args=("cc",q))

    p1.start()
    p2.start()
    p3.start()

    c1.start()
    c2.start()

    p1.join()
    p2.join()
    p3.join()
    # 在p1\p2\p3都结束后,才应该往队列里放结束信号,有几个消费者就应该放几个None
    q.put(None)
    q.put(None)

    print("")
方式二:修改版
from multiprocessing import JoinableQueue,Process#JoinableQueue是将队列取空
import time,random

def producer(name,food,q):
    for i in range(3):
        res = "%s%s" %(food,i)
        time.sleep(random.randint(1,3))
        q.put(res)
        print("%s 生产了 %s" %(name,res))

def consumer(name,q):
    while True:
        res = q.get()
        if res is None:break
        time.sleep(random.randint(1,3))
        print("%s 吃了 %s" %(name,res))
        q.task_done()#队列里面每取出一个就-1

if __name__ == '__main__':
    q=JoinableQueue()
    p1=Process(target=producer,args=("egon","包子",q))
    p2=Process(target=producer,args=("hm","汉堡",q))
    p3=Process(target=producer,args=("张飞","鹿腿",q))

    c1=Process(target=consumer,args=("fxc",q))
    c2=Process(target=consumer,args=("cc",q))
    c1.daemon=True
    c2.daemon=True

    p1.start()
    p2.start()
    p3.start()
    c1.start()
    c2.start()

    p1.join()
    p2.join()
    p3.join()

    q.join()#等待列队内被取干净
    # 主进程的代码运行完毕--->(生产者运行完毕)+队列中的数据也被取干净了->消费者没有存在的意义
方式三:最终版

猜你喜欢

转载自www.cnblogs.com/yf18767106368/p/9301577.html