11.python并发入门(part10 多进程之间实现通信,以及进程之间的数据共享)

简介:

一、进程队列。

多个进程去操作一个队列中的数据,外观上看起来一个进程队列,只是一个队列而已,单实际上,你开了多少个进程,这些进程一旦去使用这个队列,那么这个队列就会被复制多少份。

(队列=管道+锁)

这么做的主要原因就是,不同进程之间的数据是无法共享的。

下面是使用进程队列使多进程之间互相通信的示例:

下面这个例子,就是往进程队列里面put内容。

#!/usr/local/bin/python2.7

# -*- coding:utf-8 -*-

import multiprocessing

def func1(que,n):

    que.put(n+1)

    print "son process queue id is %s:" %(id(que))

if __name__ == '__main__':

    q1 = multiprocessing.Queue()  #生成一个进程队列!!!!这个队列和普通队列是不同的!!

    print "main process queue id is %s:" %(id(q1))

    for i in range(3):

        p = multiprocessing.Process(target=func1,args=(q1,i))

        p.start()

    print q1.get()

    print q1.get()

    print q1.get()


输出结果:

#windows和类unix系统运行的结果是不一样的!!在windows系统下,进程队列的id号是不同的!!

main process queue id is 4459325136:

son process queue id is 4459325136:

1

son process queue id is 4459325136:

2

son process queue id is 4459325136:

3


二、通过管道来实现进程间通信。

下面是使用管道的方式让两个进程通信的示例。

下面这段代码主要实现了父进程给子进程互相发送消息。

#!/usr/local/bin/python2.7

# -*- coding:utf-8 -*-

import multiprocessing

def func1(conn):

    conn.send("hi daddy!") #子进程给父进程发送内容。

    response = conn.recv() #子进程等待接收父进程发来的内容。

    print "respnse:%s" %(response)

    conn.close()

    print "child conn id %s" %(id(child_conn))

if __name__ == '__main__':

    parent_conn,child_conn = multiprocessing.Pipe() #使用multiprocessing的pipe类来创建出两个双向的管道对象,注意哦,这两个管道都是双向的,可以收也可以发。

    print "main child conn: %s" %(id(child_conn))

    p = multiprocessing.Process(target=func1,args=(child_conn,))

    p.start()

    print parent_conn.recv() #父进程等待接收子进程的内容。

    parent_conn.send("hi child!")  #父进程给子进程发送内容。

    p.join()

使用pipe类生成的两个管道相当于两部电话,一个给了父进程,另一个给了子进程。

官方说法如下:

The two connection objects returned by Pipe() represent the two ends of the pipe. Each connection object has send() and recv() methods (among others). Note that data in a pipe may become corrupted if two processes (or threads) try to read from or write to the same end of the pipe at the same time. Of course there is no risk of corruption from processes using different ends of the pipe at the same time.

pipe对象会创建出两个链接对象(管道),每个链接对象(管道)的两端,都可以send(发送),recv(接收)等。

不过需要注意的是!两个进程或者线程同时,去读取或者写入管道的同一端,那么数据很有可能会损坏!!


总结下进程队列和管道之间的关系:

管道和进程队列,实现的都是两个子进程之间,以及父进程和子进程之间的通信功能,它们做的都是同一件事,只不过是实现的方法不一样,它们完成的都只是进程和进程之间的通信,注意!!只是数据通信!!而不是数据共享!这个概念不要弄混了!

那什么是真正的数据共享?

当一个进程去修改某个数据,另外一个进程内部也会产生变化,这才是真正意义上在多进程之间实现的数据共享。

在举一个比较好理解的例子,假如一个列表里面有三个元素,进程1去这个列表中删除一个元素,进程2再去print这个列表时,这个列表里只剩下了两个元素。


那么如何去实现进程间的数据共享?这就要由Manager去实现了。


三、使用Manager来实现进程和进程间的数据共享。

队列和管道只是实现了数据交互,并没实现数据共享,共享就是一个进程去更改另一个进程的数据。

官方对于Managers的介绍:

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

 Manager()会返回一个 Manager对象,它控制一个python服务进程,并允许其他进程使用代理的方式来操作它们


下面是manger对象都支持哪些数据类型?

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


列表,字典,名称空间(变量),锁,递归锁,信号量,条件变量,事件,队列...等...因为有些类型博主也没有接触过......


下面是个进程间实现数据共享的例子:

#!/usr/local/bin/python2.7

# -*- coding:utf-8 -*-

import multiprocessing

def func1(dic_1,list_1,name):

    dic_1[name] = 'test'

    #dic_1['num'] = 123

    list_1.append(name)

    print "son process dict id:%s list id :%s " %(id(dic_1),id(list_1))

if __name__ == '__main__':

    with multiprocessing.Manager() as manager:

        d1 = manager.dict()  #注意这里!!如果字典和列表等数据类型,想要被进程之间共享,必须要使用manager下面封装好的类!!

        l1 = manager.list()  #这里使用的也是manager中已经封装好的特殊list!

        print "main process dict id:%s list id :%s " %(id(d1),id(l1))

        pro_list = []

        for i in range(10):

            p = multiprocessing.Process(target=func1,args=(d1,l1,str(i),))

            p.start()

            pro_list.append(p)

        for res in pro_list:

            res.join()

            print d1

            print l1






      本文转自苏浩智 51CTO博客,原文链接:http://blog.51cto.com/suhaozhi/1925925,如需转载请自行联系原作者


相关文章
|
18天前
|
安全 Python
告别低效编程!Python线程与进程并发技术详解,让你的代码飞起来!
【7月更文挑战第9天】Python并发编程提升效率:**理解并发与并行,线程借助`threading`模块处理IO密集型任务,受限于GIL;进程用`multiprocessing`实现并行,绕过GIL限制。示例展示线程和进程创建及同步。选择合适模型,注意线程安全,利用多核,优化性能,实现高效并发编程。
28 3
|
18天前
|
Python
解锁Python并发新世界:线程与进程的并行艺术,让你的应用性能翻倍!
【7月更文挑战第9天】并发编程**是同时执行多个任务的技术,提升程序效率。Python的**threading**模块支持多线程,适合IO密集型任务,但受GIL限制。**multiprocessing**模块允许多进程并行,绕过GIL,适用于CPU密集型任务。例如,计算平方和,多线程版本使用`threading`分割工作并同步结果;多进程版本利用`multiprocessing.Pool`分块计算再合并。正确选择能优化应用性能。
|
13天前
|
消息中间件 安全 数据处理
Python中的并发编程:理解多线程与多进程的区别与应用
在Python编程中,理解并发编程是提高程序性能和响应速度的关键。本文将深入探讨多线程和多进程的区别、适用场景及实际应用,帮助开发者更好地利用Python进行并发编程。
|
17天前
|
数据库 数据安全/隐私保护 C++
Python并发编程实战:线程(threading)VS进程(multiprocessing),谁才是并发之王?
【7月更文挑战第10天】Python并发对比:线程轻量级,适合I/O密集型任务,但受GIL限制;进程绕过GIL,擅CPU密集型,但通信成本高。选择取决于应用场景,线程利于数据共享,进程利于多核利用。并发无“王者”,灵活运用方为上策。
|
16天前
|
消息中间件 JSON 自然语言处理
python多进程日志以及分布式日志的实现方式
python日志在多进程环境下的问题 python日志模块logging支持多线程,但是在多进程下写入日志文件容易出现下面的问题: PermissionError: [WinError 32] 另一个程序正在使用此文件,进程无法访问。 也就是日志文件被占用的情况,原因是多个进程的文件handler对日志文件进行操作产生的。
|
15天前
|
安全 Linux 数据格式
【Linux】进程通信----管道通信(下)
【Linux】进程通信----管道通信(下)
17 0
|
15天前
|
Unix Linux
【Linux】进程通信----管道通信(上)
【Linux】进程通信----管道通信(上)
25 0
|
29天前
|
监控 Linux 应用服务中间件
探索Linux中的`ps`命令:进程监控与分析的利器
探索Linux中的`ps`命令:进程监控与分析的利器
|
4天前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
|
15天前
|
存储 缓存 安全
【Linux】冯诺依曼体系结构与操作系统及其进程
【Linux】冯诺依曼体系结构与操作系统及其进程
125 1