探究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 相关文章推荐
linux下python抓屏实现方法
May 22 Python
Python实现爬取逐浪小说的方法
Jul 07 Python
python用reduce和map把字符串转为数字的方法
Dec 19 Python
Python解析命令行读取参数--argparse模块使用方法
Jan 23 Python
python实现人脸识别经典算法(一) 特征脸法
Mar 13 Python
Python判断以什么结尾以什么开头的实例
Oct 27 Python
Python生成MD5值的两种方法实例分析
Apr 26 Python
Python转换时间的图文方法
Jul 01 Python
python批量处理文件或文件夹
Jul 28 Python
Django REST框架创建一个简单的Api实例讲解
Nov 05 Python
Python不支持 i ++ 语法的原因解析
Jul 22 Python
python 6种方法实现单例模式
Dec 15 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
让你同时上传 1000 个文件 (二)
2006/10/09 PHP
php include和require的区别深入解析
2013/06/17 PHP
php处理restful请求的路由类分享
2014/02/27 PHP
百度工程师讲PHP函数的实现原理及性能分析(二)
2015/05/13 PHP
thinkPHP自定义类实现方法详解
2016/11/30 PHP
IE中jscript/javascript的条件编译
2006/09/07 Javascript
jquery 关键字“拖曳搜索”之“拖曳”以及 图片“提示自适应放大”效果 的实现
2010/04/18 Javascript
在Ajax中使用Flash实现跨域数据读取的实现方法
2010/12/02 Javascript
基于jQuery的图片左右无缝滚动插件
2012/05/23 Javascript
单击按钮显示隐藏子菜单经典案例
2013/01/04 Javascript
JS去除字符串两端空格的简单实例
2013/12/27 Javascript
js中生成map对象的方法
2014/01/09 Javascript
js脚本获取webform服务器控件的方法
2014/05/16 Javascript
JS+CSS实现滑动切换tab菜单效果
2015/08/25 Javascript
JS实现超简洁网页title标题跑动闪烁提示效果代码
2015/10/23 Javascript
jQuery实现的自适应焦点图效果完整实例
2016/08/24 Javascript
Angular17之Angular自定义指令详解
2018/01/21 Javascript
利用hasOwnProperty给数组去重的面试题分享
2018/11/05 Javascript
JQuery+Bootstrap 自定义全屏Loading插件的示例demo
2019/07/03 jQuery
JavaScript中的各种宽高属性的实现
2020/05/08 Javascript
vue如何在用户要关闭当前网页时弹出提示的实现
2020/05/31 Javascript
[59:53]DOTA2-DPC中国联赛 正赛 VG vs Elephant BO3 第二场 3月6日
2021/03/11 DOTA
python实时分析日志的一个小脚本分享
2017/05/07 Python
Python正则表达式分组概念与用法详解
2017/06/24 Python
Python从使用线程到使用async/await的深入讲解
2018/09/16 Python
python读写csv文件方法详细总结
2019/07/05 Python
美国领先的奢侈手表在线零售商:WatchMaxx
2017/12/17 全球购物
自考毕业生自我鉴定
2013/11/04 职场文书
倡议书范文
2014/04/16 职场文书
青年志愿者活动总结
2014/04/26 职场文书
《鲁班和橹板》教学反思
2014/04/27 职场文书
俞敏洪励志演讲稿
2014/04/29 职场文书
会展策划与管理专业求职信
2014/06/09 职场文书
2014年班级工作总结
2014/11/14 职场文书
一个独生女的故事观后感
2015/06/04 职场文书
2016春季运动会通讯稿
2015/07/18 职场文书