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))

扩展: 栈

也是一种特殊的容器 特殊在于 存取顺序为 先进后出

函数调用栈

调用函数时 称之为 函数入栈

函数执行结束 称之为函数出栈

posted @ 2019-07-03 22:53  abcde_12345  阅读(384)  评论(0编辑  收藏  举报