dawn-liu

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

展望未来,基于消息传递的并发编程是大势所趋

即便是使用线程,推荐做法也是将程序设计为大量独立的线程集合,通过消息队列交换数据。

这样极大地减少了对使用锁定和其他同步手段的需求,还可以扩展到分布式系统中。

但进程间应该尽量避免通信,即便需要通信,也应该选择进程安全的工具来避免加锁带来的问题。

以后我们会尝试使用数据库来解决现在进程之间的数据共享问题。

Manager 介绍

进程间数据是独立的,可以借助于队列或管道实现通信,二者都是基于消息传递的
虽然进程间数据独立,但可以通过Manager实现数据共享,事实上Manager的功能远不止于此

A manager object returned by Manager() controls a server process which holds Python objects and allows other processes to manipulate them using proxies.

A manager returned by Manager() will support types list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value and Array.
View Code

Manager是一种较为高级的多进程通信方式,它能支持Python支持的的任何数据结构。
它的原理是:先启动一个ManagerServer进程,这个进程是阻塞的,它监听一个socket,然后其他进程(ManagerClient)通过socket来连接到ManagerServer,实现通信。

简单使用

from multiprocessing import Manager,Process
def func(dic):
    dic['count'] = dic['count'] -1
    print(dic)
 
if __name__ == '__main__':
    m = Manager()  # 创建一个server进程
    dic = m.dict({'count':100})  #这是一个特殊的字典
    p = Process(target=func,args=[dic,])
    p.start()
    p.join()

再看循环修改的例子

from multiprocessing import Manager,Process
def func(dic):
    dic['count'] = dic['count'] -1  # 每次减1
 
if __name__ == '__main__':
    m = Manager()  # 创建一个server进程
    dic = m.dict({'count':100})  #这是一个特殊的字典
    p_lst = []  # 定义一个空列表
    for i in range(100):  # 启动100个进程
        p = Process(target=func,args=[dic,])
        p_lst.append(p)  # 进程追加到列表中
        p.start()  # 启动进程
    for p in p_lst:p.join()  # 等待100个进程全部结束
    print(dic)  # 打印dic的值

多执行几次就会发现,dic的值再 0 1 3之间变化,同一个时间内有多个进程操作dic,就会发生数据错乱

所以需要加锁,结果就固定为{'count': 0}

from multiprocessing import Manager, Process, Lock


def func(dic, lock):
    lock.acquire()  # 取得锁
    dic['count'] = dic['count'] - 1  # 每次减1
    lock.release()  # 释放锁


if __name__ == '__main__':
    m = Manager()  # 创建一个server进程
    lock = Lock()  # 创建锁
    dic = m.dict({'count': 100})  # 这是一个特殊的字典
    p_lst = []  # 定义一个空列表
    for i in range(100):  # 启动100个进程
        p = Process(target=func, args=[dic, lock])
        p_lst.append(p)  # 进程追加到列表中
        p.start()  # 启动进程
    for p in p_lst: p.join()  # 等待100个进程全部结束
    print(dic)  # 打印dic的值

还有另外一种写法

from multiprocessing import Manager,Process,Lock
def func(dic,lock):
    with lock:  # 上下文管理 :必须有一个开始动作 和 一个结束动作的时候
        dic['count'] = dic['count'] -1  # 每次减1
 
if __name__ == '__main__':
    m = Manager()  # 创建一个server进程
    lock = Lock()  #创建锁
    dic = m.dict({'count':100})  #这是一个特殊的字典
    p_lst = []  # 定义一个空列表
    for i in range(100):  # 启动100个进程
        p = Process(target=func,args=[dic,lock])
        p_lst.append(p)  # 进程追加到列表中
        p.start()  # 启动进程
    for p in p_lst:p.join()  # 等待100个进程全部结束
    print(dic)  # 打印dic的值

 

使用:同一台机器上:使用 Queue

   不同机器上,使用消息中间件

posted on 2018-08-06 11:37  dawn-liu  阅读(234)  评论(0编辑  收藏  举报