• 进程之间的数据共享 -----Manager模块


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

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

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

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

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

    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

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

  • 相关阅读:
    Failed setting up proxy interface org.apache.hadoop.hbase.ipc.HRegionInterface
    关于操作权限
    什么时候才应该使用HBase?
    模块化服务规范——OSGI
    15个你可能不知道的开源云平台
    hadoop 异常记录 ERROR: org.apache.hadoop.hbase.MasterNotRunningException: Retried 7 times
    Apache nutch1.5 & Apache solr3.6
    Apache cassandra
    谈谈SAAS模式
    卸载VisualStudio插件
  • 原文地址:https://www.cnblogs.com/mmyy-blog/p/9429391.html
Copyright © 2020-2023  润新知