探究Python多进程编程下线程之间变量的共享问题


Posted in Python onMay 05, 2015

 1、问题:

群中有同学贴了如下一段代码,问为何 list 最后打印的是空值?
 

from multiprocessing import Process, Manager
import os
 
manager = Manager()
vip_list = []
#vip_list = manager.list()
 
def testFunc(cc):
  vip_list.append(cc)
  print 'process id:', os.getpid()
 
if __name__ == '__main__':
  threads = []
 
  for ll in range(10):
    t = Process(target=testFunc, args=(ll,))
    t.daemon = True
    threads.append(t)
 
  for i in range(len(threads)):
    threads[i].start()
 
  for j in range(len(threads)):
    threads[j].join()
 
  print "------------------------"
  print 'process id:', os.getpid()
  print vip_list

其实如果你了解 python 的多线程模型,GIL 问题,然后了解多线程、多进程原理,上述问题不难回答,不过如果你不知道也没关系,跑一下上面的代码你就知道是什么问题了。
 

python aa.py
process id: 632
process id: 635
process id: 637
process id: 633
process id: 636
process id: 634
process id: 639
process id: 638
process id: 641
process id: 640
------------------------
process id: 619
[]

将第 6 行注释开启,你会看到如下结果:
 

process id: 32074
process id: 32073
process id: 32072
process id: 32078
process id: 32076
process id: 32071
process id: 32077
process id: 32079
process id: 32075
process id: 32080
------------------------
process id: 32066
[3, 2, 1, 7, 5, 0, 6, 8, 4, 9]

2、python 多进程共享变量的几种方式:
(1)Shared memory:
Data can be stored in a shared memory map using Value or Array. For example, the following code

http://docs.python.org/2/library/multiprocessing.html#sharing-state-between-processes
 

from multiprocessing import Process, Value, Array
 
def f(n, a):
  n.value = 3.1415927
  for i in range(len(a)):
    a[i] = -a[i]
 
if __name__ == '__main__':
  num = Value('d', 0.0)
  arr = Array('i', range(10))
 
  p = Process(target=f, args=(num, arr))
  p.start()
  p.join()
 
  print num.value
  print arr[:]

结果:
 

3.1415927
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]

(2)Server process:

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, Queue, Value and Array.
代码见开头的例子。

http://docs.python.org/2/library/multiprocessing.html#managers
3、多进程的问题远不止这么多:数据的同步

看段简单的代码:一个简单的计数器:
 

from multiprocessing import Process, Manager
import os
 
manager = Manager()
sum = manager.Value('tmp', 0)
 
def testFunc(cc):
  sum.value += cc
 
if __name__ == '__main__':
  threads = []
 
  for ll in range(100):
    t = Process(target=testFunc, args=(1,))
    t.daemon = True
    threads.append(t)
 
  for i in range(len(threads)):
    threads[i].start()
 
  for j in range(len(threads)):
    threads[j].join()
 
  print "------------------------"
  print 'process id:', os.getpid()
  print sum.value

结果:
 

------------------------
process id: 17378
97

也许你会问:WTF?其实这个问题在多线程时代就存在了,只是在多进程时代又杯具重演了而已:Lock!
 

from multiprocessing import Process, Manager, Lock
import os
 
lock = Lock()
manager = Manager()
sum = manager.Value('tmp', 0)
 
 
def testFunc(cc, lock):
  with lock:
    sum.value += cc
 
 
if __name__ == '__main__':
  threads = []
 
  for ll in range(100):
    t = Process(target=testFunc, args=(1, lock))
    t.daemon = True
    threads.append(t)
 
  for i in range(len(threads)):
    threads[i].start()
 
  for j in range(len(threads)):
    threads[j].join()
 
  print "------------------------"
  print 'process id:', os.getpid()
  print sum.value

这段代码性能如何呢?跑跑看,或者加大循环次数试一下。。。
4、最后的建议:

    Note that usually sharing data between processes may not be the best choice, because of all the synchronization issues; an approach involving actors exchanging messages is usually seen as a better choice. See also Python documentation: As mentioned above, when doing concurrent programming it is usually best to avoid using shared state as far as possible. This is particularly true when using multiple processes. However, if you really do need to use some shared data then multiprocessing provides a couple of ways of doing so.

5、Refer:

http://stackoverflow.com/questions/14124588/python-multiprocessing-shared-memory

http://eli.thegreenplace.net/2012/01/04/shared-counter-with-pythons-multiprocessing/

http://docs.python.org/2/library/multiprocessing.html#multiprocessing.sharedctypes.synchronized

Python 相关文章推荐
python中django框架通过正则搜索页面上email地址的方法
Mar 21 Python
Python中利用函数装饰器实现备忘功能
Mar 30 Python
Python中实现参数类型检查的简单方法
Apr 21 Python
举例讲解Python设计模式编程的代理模式与抽象工厂模式
Jan 16 Python
python如何修改装饰器中参数
Mar 20 Python
Python基于百度AI的文字识别的示例
Apr 21 Python
Python小工具之消耗系统指定大小内存的方法
Dec 03 Python
python中时间、日期、时间戳的转换的实现方法
Jul 06 Python
Python 使用多属性来进行排序
Sep 01 Python
带你彻底搞懂python操作mysql数据库(cursor游标讲解)
Jan 06 Python
利用python实现逐步回归
Feb 24 Python
基于django micro搭建网站实现加水印功能
May 22 Python
浅谈Python中的数据类型
May 05 #Python
用Python实现一个简单的能够上传下载的HTTP服务器
May 05 #Python
使用Python程序抓取新浪在国内的所有IP的教程
May 04 #Python
Python版微信红包分配算法
May 04 #Python
用Python编写一个每天都在系统下新建一个文件夹的脚本
May 04 #Python
用Python编写生成树状结构的文件目录的脚本的教程
May 04 #Python
使用Python脚本将Bing的每日图片作为桌面的教程
May 04 #Python
You might like
用js实现的模拟jquery的animate自定义动画(2.5K)
2010/07/20 Javascript
js中parseInt函数浅谈
2013/07/31 Javascript
JS远程获取网页源代码实例
2013/09/05 Javascript
javascript实现图片循环渐显播放的方法
2015/02/24 Javascript
jquery动态增加删减表格行特效
2015/11/20 Javascript
js生成随机数的过程解析
2015/11/24 Javascript
基于javascript代码实现通过点击图片显示原图片
2015/11/29 Javascript
使用JS中的exec()方法构造正则表达式验证
2016/08/01 Javascript
js实现各种复制到剪贴板的方法(分享)
2016/10/27 Javascript
vue学习笔记之vue1.0和vue2.0的区别介绍
2017/05/17 Javascript
js+html5实现复制文字按钮
2017/07/15 Javascript
node文字生成图片的示例代码
2017/10/26 Javascript
微信小程序生成分享海报方法(附带二维码生成)
2019/03/29 Javascript
Node.js一行代码实现静态文件服务器的方法步骤
2019/05/07 Javascript
Tensorflow简单验证码识别应用
2017/05/25 Python
python编程使用协程并发的优缺点
2018/09/20 Python
python批量获取html内body内容的实例
2019/01/02 Python
Python 使用多属性来进行排序
2019/09/01 Python
tensorflow 模型权重导出实例
2020/01/24 Python
Python实现自动访问网页的例子
2020/02/21 Python
python程序文件扩展名知识点详解
2020/02/27 Python
详解Python3 定义一个跨越多行的字符串的多种方法
2020/09/06 Python
巧用HTML5给按钮背景设计不同的动画简单实例
2016/08/09 HTML / CSS
菲律宾旅游网站:Expedia菲律宾
2017/10/11 全球购物
RIP版本1跟版本2的区别
2013/12/30 面试题
人事主管的岗位职责
2013/11/16 职场文书
单位人事专员介绍信
2014/01/11 职场文书
中式面点餐厅创业计划书
2014/01/29 职场文书
教师自我反思材料
2014/02/14 职场文书
店铺转让协议书
2014/12/02 职场文书
幼儿学前班评语
2014/12/29 职场文书
上市公司董事长岗位职责
2015/04/16 职场文书
无工作证明怎么写
2015/06/15 职场文书
golang 实现对Map进行键值自定义排序
2021/04/28 Golang
MySQL系列之十四 MySQL的高可用实现
2021/07/02 MySQL
PostgreSQL基于pgrouting的路径规划处理方法
2022/04/18 PostgreSQL