博客
关于我
Python_生产者消费者模型、管道、数据共享、进程池
阅读量:797 次
发布时间:2023-03-09

本文共 2659 字,大约阅读时间需要 8 分钟。

生产者消费者模型、管道与数据共享的分析

生产者消费者模型

生产者消费者模型是处理数据生产与消费的经典模式,适用于分布式系统中的数据处理。生产者负责生产数据,消费者负责消费数据。这种模型通过队列进行通信,保证了数据的有序性和安全性。以下是使用Python的multiprocessing模块实现的生产者消费者模型示例:

import timeimport randomfrom multiprocessing import Process, Queuedef consumer(q):    while True:        obj = q.get()        print(f'消费了一个数据{obj}')        time.sleep(random.randint(1, 3))if __name__ == "__main__":    q = Queue()    Process(target=consumer, args=(q,)).start()    for i in range(10):        time.sleep(random.randint(1, 5))        q.put(f'food{i}')        print(f'生产了一个数据food{i}')

结果示例

运行上述代码会观察到生产者和消费者交替工作的现象,随着时间的推移,队列中的数据会被逐一消费完毕。

阻塞队列

在上述模型中,q.get()是阻塞操作,直到队列中有数据被放入为止。这保证了生产者和消费者能够高效地进行数据交换。

管道通信

管道(Pipe)是多进程间通信的基础设施,通过一个双向通道实现数据的传递。以下是一个简单的管道通信示例:

from multiprocessing import Pipe, Processdef consumer(lp, rp):    lp.close()    while True:        try:            print(rp.recv())        except EOFError:            breakif __name__ == "__main__":    lp, rp = Pipe()    Process(target=consumer, args=(lp, rp)).start()    Process(target=consumer, args=(lp, rp)).start()    Process(target=consumer, args=(lp, rp)).start()    Process(target=consumer, args=(lp, rp)).start()    Process(target=consumer, args=(lp, rp)).start()    rp.close()    for i in range(500):        lp.send(f'food{i}')    lp.close()

结果示例

运行上述代码会发现,主进程将500个“food”对象发送到管道中,随后所有进程都会退出,完成任务。

数据共享

在多进程环境下,共享数据需要谨慎处理,否则可能导致数据竞争和不一致性。普通模式下,直接使用共享数据可能会出现问题:

from multiprocessing import Manager, Process, Lockdef work(d, lock):    with lock:        d['count'] -= 1if __name__ == "__main__":    lock = Lock()    m = Manager()    dic = m.dict({'count': 100})    p_l = []    for i in range(100):        p = Process(target=work, args=(dic, lock))        p_l.append(p)        p.start()    for p in p_l:        p.join()    print(dic)

结果示例

运行上述代码后,dic中的count会减少到0,表明所有进程都完成了工作。

上下文管理模式

为了避免数据竞争,可以使用上下文管理器:

from multiprocessing import Manager, Process, Lockdef work(d, lock):    with lock:        d['count'] -= 1if __name__ == "__main__":    with Manager() as m:        dic = m.dict({'count': 100})        p_l = []        for i in range(100):            p = Process(target=work, args=(dic, lock))            p_l.append(p)            p.start()        for p in p_l:            p.join()        print(dic)

结果示例

与普通模式结果一致,dic中的count减少到0。

进程池的使用

进程池提供了更高效的任务调度方式,适用于需要多进程执行的任务。以下是一个使用进程池的示例:

import osimport timedef wahaha(num):    print(f'子{os.getpid()}')    return num ** numdef call(argv):    print(f'主{os.getpid()}')    print(argv)if __name__ == "__main__":    print('主', os.getpid())    p = Pool(5)    p.apply_async(func=wahaha, args=(50,), callback=call)    p.close()    p.join()

结果示例

运行上述代码会看到主进程和子进程交替输出信息,最终所有任务完成后,进程池关闭。

转载地址:http://djlfk.baihongyu.com/

你可能感兴趣的文章
python函数
查看>>
python----线程、进程、协程的区别及多线程详解
查看>>
python---5
查看>>
python---使用celery分布式系统异步发送短信(云通讯)来验证登录
查看>>
python--003--百分号字符串拼接、format
查看>>
Python--10、线程
查看>>
Python--Redis实战:第四章:数据安全与性能保障:第4节:复制
查看>>
python--基本代码规范
查看>>
Python--抽象类接口类
查看>>
PYTHON--欧拉习题二
查看>>
python--高级应用总结
查看>>
python-520表白代码,我看谁说程序员不懂浪漫,送你几套表白代码,一步到位
查看>>
Python-Asyncio TypeError:无法在‘;等待‘;表达式中使用对象DICT
查看>>
Python-AttributeError:‘;dict&39;对象没有属性‘;序列‘;
查看>>
Python-ldap:是否可以在不显式写入密码的情况下进行绑定?
查看>>
python出现 unknown encoding: idna 的处理方法
查看>>
Python出现 RuntimeError: dictionary changed size during iteration 的解决方法
查看>>
Python-numpy(2)数组的操作
查看>>
Python-Numpy的tile函数用法
查看>>
python-open函数
查看>>