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()
#用爬虫比较好 二期视频补充了很多相关的知识