1、守护进程
守护进程其实就是一个'子进程'
守护=>伴随
守护进程会伴随主进程的代码运行完毕后而死掉
2、为何用守护进程
关键字就两个"
进程:
当父进程需要将一个任务并发出去执行,需要将该任务放到一个子进程里
守护:
当该子进程内的代码在父进程代码运行完毕后就没有存在的意义了,就应该将该
子进程设置为守护进程,会在父进程代码结束后死掉。
from multiprocessing import Process import time,os def task(): print('%is running'%os.getpid()) #获得的事进程的pid ppid查看其父进程的id号 time.sleep(3) if __name__=='__main__': p=Process(target=task) p.daemon=True#一定要放到p.start()之前 p.daemon为其守护进程 p.start() print('主') print('%主is running' % os.getpid()) #如何把一个子进程做成守护进程呢? #到底是什么场景需要子进程? #生产者消费者模型的时候
互斥锁
错误1:一张票卖了10次 (购票操作不应该并发,而是应该串行)
from multiprocessing import Process import json import os import time import random def check(): time.sleep(random.randint(1,3))#1~3 模拟网络延迟 with open('db.txt','rt',encoding='utf-8') as f: dic=json.load(f) print('%s查看到剩余票数[%s]'%(os.getpid(),dic['count'])) #用多个进程来模拟多个人的 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) print('%s购票成功'%os.getpid()) else: print('%s没有余票'%os.getpid()) def task(): #查票 check() #购票 get() if __name__ == '__main__': for i in range(10): p=Process(target=task) p.start() #db.txt文件 {"count": 0}
错误2:查票应该是并发的 购票应该是串行的,保证数据安全的核心是并发编程串行
from multiprocessing import Process import json import os import time import random def check(): time.sleep(random.randint(1,3))#1~3 模拟网络延迟 with open('db.txt','rt',encoding='utf-8') as f: dic=json.load(f) print('%s查看到剩余票数[%s]'%(os.getpid(),dic['count'])) #用多个进程来模拟多个人的 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) print('%s购票成功'%os.getpid()) else: print('%s没有余票'%os.getpid()) def task(): #查票 check() #购票 get() if __name__ == '__main__': for i in range(10): p=Process(target=task) p.start() p.join() #db.txt文件 {"count": 0}
正确的方法:加互斥锁:
from multiprocessing import Process,Lock import json import os import time import random def check(): time.sleep(random.randint(1,3))#1~3 模拟网络延迟 with open('db.txt','rt',encoding='utf-8') as f: dic=json.load(f) print('%s查看到剩余票数[%s]'%(os.getpid(),dic['count'])) #用多个进程来模拟多个人的 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) print('%s购票成功'%os.getpid()) else: print('%s没有余票'%os.getpid()) def task(mutex): #查票 check() #购票 mutex.acquire()#互斥锁不能连续的acquire,必须是release后才能重新acquire get() mutex.release() # with mutex:#简写版 # get() if __name__ == '__main__': mutex=Lock() for i in range(10): p=Process(target=task,args=(mutex,)) p.start() #db.txt文件 # {"count": 0} #互斥锁:将并发变成串行,牺牲了效率保证了数据安全
互斥锁跟之前的join思路一样,都是将并发编程串行。join是真正意义上的穿行 join所有的都串行,join是查票都变成串行了,所以join将要执行的代码编程整体的串行。
互斥锁:可以将部分代码(只涉及到修改共享数据的代码)变成串行
join是将执行任务的所有代码整体串行
进程间通信
# IPC:进程间通信,有两种实现方式 #inter progress communicate 进程之间交流 # 1、pipe: #基于管道的 # 2、queue:pipe+锁 #基于队列的 队列是管道加锁实现的 管道和队列都是为了实现进程之间通信的 from multiprocessing import Queue 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())
之前借助进程之间通信靠文件,文件是硬盘空间
硬盘的效率太低
需要另外一种介质来打破内存间介质的通信
需要一个共享的内存空间
在linux系统中 free -m查看共享的内存
进程间的通信应该用内存空间而不是硬盘空间
生产者消费者模型
生产者消费者模型
该模型中包含两类重要的角色:
1、生产者:将负责造数据的任务比喻为生产者
2、消费者:接收生产者造出的数据来做进一步的处理,该类人物被比喻成消费者
实现生产者消费者模型三要素
1、生产者
2、消费者
3、队列
什么时候用该模型:
程序中出现明显的两类任何,一类任务是负责生产,另外一类任务是负责处理生产的数据的
该模型的好处:
1、实现了生产者与消费者解耦和
2、平衡了生产力与消费力,即生产者可以一直不停地生产,消费者可以不停地处理,因为二者
不再直接沟通的,而是跟队列沟通
import time import random from multiprocessing import Process,Queue def consumer(name,q): while True: res=q.get() time.sleep(random.randint(1,3)) print(' 33[46m消费者===》%s 吃了 %s 33[0m' %(name,res)) def producer(name,q,food): for i in range(5): time.sleep(random.randint(1,2)) res='%s%s' %(food,i) q.put(res) print(' 33[45m生产者者===》%s 生产了 %s 33[0m' %(name,res)) if __name__ == '__main__': #1、共享的盆 q=Queue() #2、生产者们 p1=Process(target=producer,args=('egon',q,'包子')) p2=Process(target=producer,args=('刘清政',q,'泔水')) p3=Process(target=producer,args=('杨军',q,'米饭')) #3、消费者们 c1=Process(target=consumer,args=('alex',q)) c2=Process(target=consumer,args=('梁书东',q)) p1.start() p2.start() p3.start() c1.start() c2.start() #用爬虫比较好 二期视频补充了很多相关的知识