优化抢票
加入Lock
lock.acquire() 锁住
lock.release()释放锁头
- 进程锁把所著的代码编程串行,
- join 是把所有的子进程变成了串行。
from multiprocessing import Process,Lock
import json,time,os
def search():
time.sleep(1) # 模拟网络io
with open('db.txt',mode='rt',encoding='utf-8') as f:
res = json.load(f)
print(f'还剩{res["count"]}')
def get():
with open('db.txt',mode='rt',encoding='utf-8') as f:
res = json.load(f)
# print(f'还剩{res["count"]}')
time.sleep(1) # 模拟网络io
if res['count'] > 0:
res['count'] -= 1
with open('db.txt',mode='wt',encoding='utf-8') as f:
json.dump(res,f)
print(f'进程{os.getpid()} 抢票成功')
time.sleep(1.5) # 模拟网络io
else:
print('票已经售空啦!!!!!!!!!!!')
def task(lock):
search()
# 锁住
lock.acquire()
get()
lock.release()
# 释放锁头
if __name__ == '__main__':
lock = Lock() # 写在主进程是为了让子进程拿到同一把锁.
for i in range(15):
p = Process(target=task,args=(lock,))
p.start()
# p.join()
# 进程锁 是把锁住的代码变成了串行
# join 是把所有的子进程变成了串行
# 为了保证数据的安全,串行牺牲掉效率.
队列
- ipc机制 进程通讯
- 管道:pipe 基于共享的内存空间
- 队列:pipe+锁 queue
put()放东西
get.()拿东西,如果拿的东西拿多了那么,就会一直等着拿值,不会报错
Queue() 队列满了,再放值就会阻塞。
block为阻塞状态,True 默认阻塞状态是对的,满了就会阻塞,False就是错的,则会抛错
block=True 如果满了会等待,
timeout=n,n秒后如果队列中还是满的就会报错
Queue不适合传大的文件
生产者消费者模型
JoinableQueue()
task_done()先放对队列一个任务,然后完成了一次任务#向q.join()发送一次信号,证明一个数据已经被取走了
q=JoinableQueue()
q.join() #计数器不为0的时候,阻塞等待计数器为0后通过
包子的故事 简单的提高生产者生产效率和消费者消费效率,生产者
'''
生产者: 生产数据的任务
生产者--队列(盆)-->消费者
生产者可以不停的生产,达到了自己最大的生产效率,消费者可以不停的消费,也达到了自己最大的消费效率.
生产者消费者模型大大提高了生产者生产的效率和消费者消费的效率.
# 补充: queue不适合传大文件,通常传一些消息.
'''
from multiprocessing import Process,Queue
def producer (q,name,food):
for i in range(10):
print(f'{name}生产了{food}{i}')
time.sleep(random.randint(1,3))
res=f'{food}{i}'
q.put(res)
def consumer(q,name):
#消费者
while True:
res=q.get()
print(f'{name}吃了{res}')
q.task_done()
if __name__ =='__main__':
q=JoinableQueue()
p1 = Process(target=producer,args=(q,'rocky','包子'))
p2 = Process(target=producer,args=(q,'mac','韭菜'))
p3 = Process(target=producer,args=(q,'nick','蒜泥'))
c1 = Process(target=consumer,args=(q,'成哥'))
c2 = Process(target=consumer,args=(q,'浩南哥'))
c1.daemon=True
c2.daemon=True
p_lst=[p1,p2,p3,c1,c2]
for p in p_lst:
p.start()
p1.join()
p1.join()
p2.join()
p3.join() # 生产者生产完毕
# q.put(None)# 几个消费者put几次
# q.put(None)
q.join() # 分析
# 生产者生产完毕--这是主进程最后一行代码结束--q.join()消费者已经取干净了,没有存在的意义了.
#这是主进程最后一行代码结束,消费者已经取干净了,没有存在的意义了.守护进程的概念.