探究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正则匹配查询港澳通行证办理进度示例分享
Dec 27 Python
python控制台英汉汉英电子词典
Apr 23 Python
python实现数独算法实例
Jun 09 Python
利用Python破解斗地主残局详解
Jun 30 Python
Python中django学习心得
Dec 06 Python
python 爬虫 批量获取代理ip的实例代码
May 22 Python
小白入门篇使用Python搭建点击率预估模型
Oct 12 Python
Python2比较当前图片跟图库哪个图片相似的方法示例
Sep 28 Python
Python+OpenCV实现将图像转换为二进制格式
Jan 09 Python
Python网络爬虫信息提取mooc代码实例
Mar 06 Python
Python+Xlwings 删除Excel的行和列
Dec 19 Python
pytest fixtures装饰器的使用和如何控制用例的执行顺序
Jan 28 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提取中文首字母
2008/04/09 PHP
PHP实现读取一个1G的文件大小
2013/08/24 PHP
用PHP生成excel文件到指定目录
2015/06/22 PHP
JavaScript 节点操作 以及DOMDocument属性和方法
2007/12/06 Javascript
jquery 简短右键菜单 多浏览器兼容
2010/01/01 Javascript
window.event快达到全浏览器支持了,以后使用就方便了
2011/11/30 Javascript
可以用鼠标拖动的DIV实现思路及代码
2013/10/21 Javascript
jquery隐藏标签和显示标签的实例
2013/11/11 Javascript
jQuery实现拖动调整表格单元格大小的代码实例
2015/01/13 Javascript
JavaScript中的Reflect对象详解(ES6新特性)
2016/07/22 Javascript
JavaScript鼠标特效大全
2016/09/13 Javascript
基于jQuery实现的幻灯图片切换
2016/12/02 Javascript
jquery实现限制textarea输入字数的方法
2017/09/06 jQuery
Webpack之tree-starking 解析
2018/09/11 Javascript
解决微信小程序调用moveToLocation失效问题【超简单】
2019/04/12 Javascript
JavaScript数组排序小程序实现解析
2020/01/13 Javascript
用python删除java文件头上版权信息的方法
2014/07/31 Python
Python基于回溯法子集树模板解决找零问题示例
2017/09/11 Python
django的登录注册系统的示例代码
2018/05/14 Python
python统计字母、空格、数字等字符个数的实例
2018/06/29 Python
Python2和Python3.6环境解决共存问题
2018/11/09 Python
Python语言快速上手学习方法
2018/12/14 Python
Python计算不规则图形面积算法实现解析
2019/11/22 Python
win10从零安装配置pytorch全过程图文详解
2020/05/08 Python
解决pycharm修改代码后第一次运行不生效的问题
2021/02/06 Python
CSS3网格的三个新特性详解
2014/04/04 HTML / CSS
解决Firefox下不支持outerHTML问题代码分享
2014/06/04 HTML / CSS
化工专业应届生求职信
2013/11/08 职场文书
党员教师一句话承诺
2014/05/30 职场文书
音乐之声音乐广播稿
2014/09/10 职场文书
爱护公共设施演讲稿
2014/09/13 职场文书
2014年酒店工作总结与计划
2014/11/17 职场文书
个人工作表现自我评价
2015/03/06 职场文书
综治目标管理责任书
2015/05/11 职场文书
酒店员工管理制度
2015/08/05 职场文书
火锅店的开业营销方案范本!
2019/07/05 职场文书