• 进程间的通讯


    进程之间的通信

    进程之间原则上是不共享数据的

    1. 基于文件+ 锁的形式: 效率低,麻烦.
    2. 基于队列: 推荐使用形式.
    3. 基于管道: 管道自己加锁, 底层可以会出现数据丢失损坏.
    4. 第3方模块

    基于文件通信

    基于文件的抢票模型

    # 虽然进程间内存级别不可以通讯 但是基于文件是可以通讯 但我们不常用
    # 查表并发 买票串行
    from multiprocessing import Process
    from multiprocessing import Lock
    import json
    import time
    import random
    import os
    def search():
        time.sleep(random.randint(1,3))
        with open('ticket.json',encoding='utf-8',mode='r')as f1:
            dic=json.load(f1)
            print(f'{os.getpid()}查看了票数剩余{dic["count"]}')
    
    def paid():
        with open('ticket.json',encoding='utf-8',mode='r')as f1:
            dic=json.load(f1)
        if dic['count']>0:
            dic['count']-=1
            time.sleep(random.randint(1,3))
            with open('ticket.json',encoding='utf-8',mode='w') as f1:
                json.dump(dic,f1)
            print(f'用户{os.getpid()}购买成功')
        else:
            print(f'用户{os.getpid()}购买失败')
    def task(lock):
        search()
        lock.acquire()
        paid()
        lock.release()
    
    if __name__ == '__main__':
        lock = Lock()
        for i in range(4):
            p=Process(target=task,args=((lock,)))
            p.start()
    

    基于队列通信

    队列

    就是存在于内存中的一个容器,最大的一个特点; 队列的特性就是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()}')
    

    基于管道

    Pipe通信机制,
    Pipe常用于两个进程,两个进程分别位于管道的两端
    Pipe方法返回(conn1,conn2)代表一个管道的两个端,Pipe方法有duplex参数,默认为True,即全双工模式,若为FALSE,conn1只负责接收信息,conn2负责发送,
    send和recv方法分别为发送和接收信息。
    coding:utf-8
    
    
    import multiprocessing
    import os,time,random
    
    #写数据进程执行的代码
    def proc_send(pipe,urls):
        #print 'Process is write....'
        for url in urls:
    
            print 'Process is send :%s' %url
            pipe.send(url)
            time.sleep(random.random())
    
    #读数据进程的代码
    def proc_recv(pipe):
        while True:
            print('Process rev:%s' %pipe.recv())
            time.sleep(random.random())
    
    if __name__ == '__main__':
        #父进程创建pipe,并传给各个子进程
        pipe = multiprocessing.Pipe()
        p1 = multiprocessing.Process(target=proc_send,args=(pipe[0],['url_'+str(i) for i in range(10) ]))
        p2 = multiprocessing.Process(target=proc_recv,args=(pipe[1],))
        #启动子进程,写入
        p1.start()
        p2.start()
    
        p1.join()
        p2.terminate()
    
    运行结果; 
    
  • 相关阅读:
    求欧拉路径模版 fleury算法
    回学校前的计划
    高斯消元模版
    usaco 3.2 Stringsobits 数位dp
    dijkstra模版
    codeforces AIM Tech Round (Div. 2)
    bnuoj 51275 并查集按深度合并建树
    bzoj3674: 可持久化并查集
    poj2104 求区间第k大 可持久化线段树
    Miller_Rabin判断素数模版
  • 原文地址:https://www.cnblogs.com/saoqiang/p/12388474.html
Copyright © 2020-2023  润新知