python 多进程数据交互及共享

多线程和多进程最大的不一样在于,多进程中,同一个变量,各自有一份拷贝存在于每一个进程中,互不影响,而多线程中,全部变量都由全部线程共享,因此,任何一个变量均可以被任何一个线程修改,所以,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。python

不一样进程之间内存是不共享的,要实现两个进程间的数据交换,能够用如下方法:服务器

queues

使用方法和threading里面的queue差很少多线程

from multiprocessing import Process,Queue

def f(q):
    q.put([2,None,'hello'])

if __name__ =='__main__':
    q = Queue()
    p = Process(target=f,args=(q,))
    p.start()
    print(q.get())
    p.join()

 运行结果app

[2, None, 'hello']

多进程中,对于一个变量,每一个进程都是复制了一份,因此每一个进程之间修改数据互不影响。 Queue()方法至关于第三方,把进程A的数据序列化后传给进程B 反序列化获得数据。并非一个共享的变量。而是实现了数据的传递。socket

Pipes 管道

相似于socket 一端发送,一端接收,实现通讯。spa

from multiprocessing import Process,Pipe

def f(conn):
    conn.send([5,'hello'])
    conn.close()


if __name__ =='__main__':
    parent_conn,child_conn = Pipe()
    p = Process(target=f,args=(child_conn,))
    p.start()
    print(parent_conn.recv())
    p.join()

 运行结果线程

[5, 'hello']

 发送方和接收方的关系,也和socket相似,发送方发送几回,接收方就要接收几回。接收方若是接收的次数多于发送方,那么接收方就会卡住,直到发送方在发送一次。代理

相互通讯对象

def f(conn):
    conn.send([5,'hello'])   #发送数据
    print(conn.recv())         #接收数据
    conn.close()


if __name__ =='__main__':
    parent_conn,child_conn = Pipe()
    p = Process(target=f,args=(child_conn,))
    p.start()
    print(parent_conn.recv())         #接收数据
    parent_conn.send("hehe你好")  #发送数据
    p.join()

 Managersblog

由manager()返回的manager对象控制一个包含Python对象的服务器进程,并容许其余进程使用代理来操做它们。

由manager()返回的管理器将支持类型列表、命令、名称空间、锁、RLock、信号量、BoundedSemaphore、Condition、Event、Barrier、Queue、Value和Array。

from multiprocessing import Process, Manager


def f(d, l):
    d[1] = '1'
    d['2'] = 2
    d[0.25] = None
    l.append(1)
    print(l)


if __name__ == '__main__':
    with Manager() as manager:
        d = manager.dict()  #生成一个字典,能够在多个进程中传递和共享。

        l = manager.list(range(5)) #生成一个列表,在多个进程中传递和共享。
        p_list = []    #存放进程对象
        for i in range(10):
            p = Process(target=f, args=(d, l))
            p.start()
            p_list.append(p)
        for res in p_list:
            res.join()  #等待进程结束

        print(d)
        print(l)

 运行结果

[0, 1, 2, 3, 4, 1]
[0, 1, 2, 3, 4, 1, 1]
[0, 1, 2, 3, 4, 1, 1, 1]
[0, 1, 2, 3, 4, 1, 1, 1, 1]
[0, 1, 2, 3, 4, 1, 1, 1, 1, 1]
[0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1]
[0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1]
[0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1]
[0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
{0.25: None, 1: '1', '2': 2}
[0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

 以上实现了进程之间的数据共享,不是数据传递,而是真正的共享。而且能够同时修改。

Manager()内部有加锁机制,不容许两个进程同时修改一份数据,由于进程的数据是独立的。

相关文章
相关标签/搜索