互斥锁
问什么要有锁
规范运行顺序 保证数据安全
多个进程依次执行 将并发变成了串行 谁先抢到锁先执行 当这个程序遇到了io阻塞 会切换到其他进程 当运行到 加锁的代码发现他没有 就不会运行这个进程了 以为锁只有一个进程拥有 保证了结果
注意锁必须要同一把
多用于 抢购 依次执行
互斥锁与join区别共同点? (面试题)
# 互斥锁与join区别共同点? (面试题)
# 共同点: 都是完成了进程之间的串行.
# 区别: join认为控制的进程串行,互斥锁是随机的抢占资源.保证了公平性
利用锁抢票的实列 进程之间的通信实例.
# 业务需求分析:
# 买票之前先要查票,必须经历的流程: 你在查票的同时,100个人也在查本此列票. 查票 并发 买串
# 买票时,你要先从服务端获取到票数,票数>0 ,买票,然后服务端票数减一. 中间肯定有网络延迟.
from multiprocessing import Process
from multiprocessing import Lock
import time
import json
import os
import random
# 多进程原则上是不能互相通信的,它们在内存级别数据隔离的.不代表磁盘上数据隔离.
# 它们可以共同操作一个文件.
def search():
time.sleep(random.random())#默认0到1
with open('db.json',encoding='utf-8',mode='r') as f1:
dic=json.load(f1)
print(f"剩余票数{dic['count']}")
def get():
with open('db.json',encoding='utf-8',mode='r') as f1:
dic = json.load(f1)
time.sleep(random.randint(1,2))
if dic['count']>0:
dic['count']-=1
with open('db.json',mode='w',encoding='utf-8')as f2:
json.dump(dic,f2)
else:print('没票了')
def task(lock):
search()
lock.acquire()#加锁
get()
lock.release()#解锁
if __name__ == '__main__':
lock=Lock()#生成一把锁
for i in range(5):#生成5个进程
p=Process(target=task,args=((lock,)))
p.start()#发起进程运行
进程之间的通信:
进程之间的通信:
1. 基于文件+ 锁的形式: 效率低,麻烦.
2. 基于队列: 推荐使用形式.
3. 基于管道: 管道自己加锁, 底层可以会出现数据丢失损坏.
队列.
什么是队列
就是存在于内存中的一个容器,最大的一个特点; 队列的特性就是FIFO.完全支持先进先出的原则.
from multiprocessing import Queue
q = Queue(3) #可以设置元素个数maxsize是默认参数 括号不填默认2147483647与系统有关
# q.put(func)#插入数据 可以插入对象与数据类型 当插入过多到达队列个数会夯住
# print(q.get())#读取队列数据 get一次读一次 单队列没数据了就会夯住
队列的特殊参数
# q.put(333,block=False)# 改成False 超过了设置数 不阻塞了 直接报错.
# q.put(333,timeout=3) # 延时报错,超过三秒再put不进数据,就会报错.
# q.get(333,block=False) # 改成False 取不出了 不阻塞了 直接报错.
# q.get(333,timeout=3) # 等3秒还 取不出了 不阻塞了 直接报错.
进程之间的通信实例.
就是利用队列 容器
# 小米:抢手环4.预期发售10个.
# 有100个人去抢.
from multiprocessing import Process
import time
from multiprocessing import Queue
import os
def task(q):
try:
q.put(os.getpid(),block=False)#队列满了报错
except Exception:
return
if __name__ == '__main__':
q=Queue(10)#同一个队列
for i in range(50):
p=Process(target=task,args=((q,)))
p.start()
for i in range(1,11):
print(f'排名{i}号的,用户{q.get()}')
生产者消费者模型
本质 队列间通信
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
多个进程实现并发的效果: 生产者消费者模型.
3个成员 生产者 消费者 容器
模型, 设计模式,归一化设计, 理论等等,教给你一个编程思路.如果以后遇到类似的情况,直接套用即可.
如果没有容器, 生产者与消费者强耦合性.不合理.所以我们要有一个容器,缓冲区.平衡了生产力与消费力.
什么是生产者
生产数据 把数据放在容器中 这个进程就是生产者
什么是消费者
在容器中取数据的进程 这个进程就是消费者
容器
就是缓冲区(队列).一个缓冲区,平衡了生产者和消费者的处理能力。.提高了效率