探究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连接mysql数据库示例(做增删改操作)
Dec 31 Python
Python算法应用实战之栈详解
Feb 04 Python
python利用urllib和urllib2访问http的GET/POST详解
Sep 27 Python
Python3中的列表,元组,字典,字符串相关知识小结
Nov 10 Python
Python爬虫小技巧之伪造随机的User-Agent
Sep 13 Python
详解python 爬取12306验证码
May 10 Python
解决python web项目意外关闭,但占用端口的问题
Dec 17 Python
python每5分钟从kafka中提取数据的例子
Dec 23 Python
python实现Oracle查询分组的方法示例
Apr 30 Python
python能在浏览器能运行吗
Jun 17 Python
基于Python爬取素材网站音频文件
Oct 21 Python
Python保存并浏览用户的历史记录
Apr 29 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
PHP与MySQL开发中页面出现乱码的一种解决方法
2007/07/29 PHP
php 更新数据库中断的解决方法
2009/06/05 PHP
php把数据表导出为Excel表的最简单、最快的方法(不用插件)
2014/05/10 PHP
php构造方法中析构方法在继承中的表现
2016/04/12 PHP
PHP编程获取音频文件时长的方法【基于getid3类】
2017/04/20 PHP
使用Zttp简化Guzzle 调用
2017/07/02 PHP
PHP copy函数使用案例代码解析
2020/09/01 PHP
jQuery EasyUI API 中文文档 - Spinner微调器使用
2011/10/21 Javascript
举例详解JavaScript中Promise的使用
2015/06/24 Javascript
浅谈Nodejs观察者模式
2015/10/13 NodeJs
深入学习jQuery Validate表单验证(二)
2016/01/18 Javascript
Kendo Grid editing 自定义验证报错提示的解决方法
2016/11/18 Javascript
ubuntu编译nodejs所需的软件并安装
2017/09/12 NodeJs
Vue基础学习之项目整合及优化
2019/06/02 Javascript
送你43道JS面试题(收藏)
2019/06/17 Javascript
JavaScript 面向对象程序设计详解【类的创建、实例对象、构造函数、原型等】
2020/05/12 Javascript
JS实现选项卡插件的两种写法(jQuery和class)
2020/12/30 jQuery
[06:35]2014DOTA2国际邀请赛 老男孩梦圆西雅图中国军团世界最强
2014/07/22 DOTA
Python使用内置json模块解析json格式数据的方法
2017/07/20 Python
python实现决策树分类
2018/08/30 Python
详解如何为eclipse安装合适版本的python插件pydev
2018/11/04 Python
python3 实现调用串口功能
2019/12/26 Python
Tensorflow tf.tile()的用法实例分析
2020/05/22 Python
Python 使用Opencv实现目标检测与识别的示例代码
2020/09/08 Python
Numpy实现卷积神经网络(CNN)的示例
2020/10/09 Python
Python .py生成.pyd文件并打包.exe 的注意事项说明
2021/03/04 Python
菲律宾票务网站:StubHub菲律宾
2018/04/21 全球购物
Urban Decay官方网站:美国化妆品品牌
2020/06/04 全球购物
外贸采购员求职的自我评价
2013/11/26 职场文书
科研先进个人典型材料
2014/01/31 职场文书
软件部经理岗位职责范本
2014/02/25 职场文书
爱心活动计划书
2014/04/26 职场文书
史学专业毕业生求职信
2014/05/09 职场文书
部门活动策划方案
2014/08/16 职场文书
python字符串常规操作大全
2021/05/02 Python
用Python selenium实现淘宝抢单机器人
2021/06/18 Python