Python入门学习笔记15(进程间数据共享)

Python中的多线程实际上是伪多线程,无法利用多核CPU的并列运算优势,所以Python多线程适合用在IO密集型的程序中。

而cpu运算密集型的程序的并发应该使用多进程。

多进程之间的数据交互主要有Queue、Pipe和Manager,其中队列Queue和管道Pipe只能应用于相同主进程创建出来的进程间的数据交换,

Manager则是可以应用于无关的两个进程间进行数据共享。

Queue

进程Queue与线程queue用法基本相同,但是Queue必须作为子进程的传入参数,否则因为不同进程内存独立的缘故是无法访问主进程中定义的Queue的。

import time
import multiprocessing
from multiprocessing import Queue
from multiprocessing import Lock

pq = Queue()

"""
注意多进程Queue必须作为参数传递给子进程,否则子进程是无法获取父进程中的变量的
多进程Queue的实质是将Queue拷贝到各个进程之中,任何一个进程做出修改都会同步到其他进程的拷贝上
"""
def pqGet(pq,lock):
    while True:
        item = pq.get()
        pq.put("a")
        #进程锁,防止屏幕输出混乱
        lock.acquire()
        print(item)
        lock.release()
        time.sleep(1)

if __name__ == "__main__":
    #注意锁必须作为传入参数
    lock = Lock()
    for i in range(100):
        pq.put(i)
    for i in range(5):
        p = multiprocessing.Process(target = pqGet,args=(pq,lock,))
        p.start()

Pipe

管道Pipe一般用于两个进程间的数据交互。管道两端会自动进入阻塞状态。

import multiprocessing
from multiprocessing import Pipe

def func(conn):
    print(conn.recv())
    conn.send([1,2,3,"asd"])

if __name__ == "__main__":
    connFrom, connTo = Pipe()
    connFrom.send("hello")
    p = multiprocessing.Process(target=func,args=(connTo,))
    p.start()
    print(connFrom.recv())

Manager

Manager是一种高级的进程间数据共享的方法,支持Python所有的数据结构。

与Queue和Pipe不同,Manager并不限定必须是同一父进程创建的进程间数据交换。

Manager的本质是启动一个ManagerSever进程监听socket其它进程通过socker连接ManagerServer实现通信

from multiprocessing import Process, Manager
import multiprocessing,time

def func(lst,index):
    print("[%d]first:" %index,lst)
    lst.append(100)
    print("[%d]second:" %index,lst)
    time.sleep(1)

if __name__ == '__main__':
    mng = Manager()
    lst = mng.list([1,2,3,4,5])
    """
    对于manager的复杂数据类型,必须在创建的时候一次性赋值
    在创建之后的修改提交是不起作用的,所以下面第二第三条赋值语句是无效的
    """
    lst[1] = list([1, 2])
    lst[1].append(0.1)#err
    lst[1][1] = "hello"#err


    plst = []
    for i in range(2):
        p = multiprocessing.Process(target=func,args=(lst,i,))
        p.start()
        plst.append(p)

    for p in plst:
        p.join()

    print("main:",lst)

Manager有一个必须注意的点,

对于manager的复杂数据类型,必须在创建或修改的时候一次性赋值。

在创建之后的修改提交是不起作用的,详见上面的示例程序

猜你喜欢

转载自www.cnblogs.com/Hexdecimal/p/9418527.html