IPC和队列Queue
IPC
(Inter-Process Communication)
空间复用中内存隔离开了多个进程,不能直接交互
IPC指的就是进程间通讯
实现方式 :
1.创建一个共享文件
缺点: 效率较低
优点: 理论上交换的数据量可以非常大
适用于: 交互不频繁 且数据量较大的情况
2.共享内存 (主要方式)
缺点: 数据量不能太大
优点: 效率高
适用于: 交互频繁,但是数据量小
3.管道
管道也是基于文件的 它是单向的 编程比较复杂
4.socket
用于网络间通信
共享内存的第一种方式
- Manger不写文件实现抢票
可以为我们创建 进程间同步的容器,但是没有处理安全问题 ,所以并不常用
from multiprocessing import Process, Lock, Manager
def show(ticket):
'''查票'''
print(ticket)
print('当前剩余票数', ticket['count'])
def buy(ticket):
'''买票'''
print(ticket)
count = ticket['count']
if count > 0:
count -= 1
ticket['count'] = count
print('抢票成功')
else:
print('没有票')
def task(lock, ticket):
# print(ticket)
show(ticket)
lock.acquire() # 安全问题需要自己另外加锁
buy(ticket)
lock.release()
if __name__ == '__main__':
ticket = {'count': 1}
m = Manager()
sync_ticket = m.dict(ticket)
lock = Lock()
ps = []
for i in range(5):
p = Process(target=task, args=(lock, sync_ticket))
p.start()
ps.append(p)
for p in ps: # 必须要用join(),否则传入子进程的不是字典,不知道为什么
p.join()
注意:必须要用join(),否则传入子进程的就不是一个字典了,不清楚原因
Queue
Queue 翻译为队列 是一种特殊的容器 特殊之处在于存取顺序为先进先出
Queue的一些常用属性
方法名 | 作用 |
---|---|
Queue([maxsize]) | 创建共享的进程队列。maxsize是队列中允许的最大项数。如果省略此参数,则无大小限制。 |
q.get( [ block [ ,timeout ] ] ) | 返回q中的一个项目。如果q为空,此方法将阻塞,直到队列中有项目可用为止。 |
q.put(item [, block [,timeout ] ] ) | 将item放入队列。如果队列已满,此方法将阻塞至有空间可用为止。 |
q.qsize() | 返回队列中目前项目的正确数量。 |
q.empty() | 如果调用此方法时 q为空,返回True。 |
q.full() | 如果q已满,返回为True. |
q.close() | 关闭队列,防止队列中加入更多数据。 |
方法作用补充:
Queue : 底层队列使用管道和锁定实现。另外,还需要运行支持线程以便队列中的数据传输到底层管道中。
get() : block用于控制阻塞行为,默认为True.如果设置为False,将引发Queue.Empty异常(定义在Queue模块中)。timeout是可选超时时间,用在阻塞模式中。如果在制定的时间间隔内没有项目变为可用,将引发Queue.Empty异常。
put() : block控制阻塞行为,默认为True。如果设置为False,将引发Queue.Empty异常(定义在Queue库模块中)。timeout指定在阻塞模式中等待可用空间的时间长短。超时后将引发Queue.Full异常。
qsize() : 此函数的结果并不可靠,因为在返回结果和在稍后程序中使用结果之间,队列中可能添加或删除了项目。在某些系统上,此方法可能引发NotImplementedError异常。
empty() : 如果其他进程或线程正在往队列中添加项目,结果是不可靠的。也就是说,在返回和使用结果之间,队列中可能已经加入新的项目。
full() : 由于线程的存在,结果也可能是不可靠的
close() : 调用此方法时,后台线程将继续写入那些已入队列但尚未写入的数据,但将在此方法完成时马上关闭。如果q被垃圾收集,将自动调用此方法。关闭队列不会在队列使用者中生成任何类型的数据结束信号或异常。例如,如果某个使用者正被阻塞在get()操作上,关闭生产者中的队列不会导致get()方法返回错误。
可以帮我们完成进程间通讯
from multiprocessing import Queue
q = Queue(2) # 创建队列 并且同时只能存储2个元素
q.put(1)
q.put(2)
# q.put(3,block=True,timeout=3) # 默认是阻塞的 当容器中没有位置了就阻塞 直到有人从里面取走元素为止
# block:是否阻塞,默认是True,如果为False就不会阻塞,但是满了会报错
# timeout:阻塞等待的时间,超出就不阻塞
print(q.get())
print(q.get())
print(q.get(block=True,timeout=3))
扩展: 栈
也是一种特殊的容器 特殊在于 存取顺序为 先进后出
函数调用栈
调用函数时 称之为 函数入栈
函数执行结束 称之为函数出栈