探究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框架实现支付宝即时到帐接口
May 17 Python
Python 爬虫模拟登陆知乎
Sep 23 Python
Python实现按特定格式对文件进行读写的方法示例
Nov 30 Python
Python获取当前函数名称方法实例分享
Jan 18 Python
python 列表递归求和、计数、求最大元素的实例
Nov 28 Python
浅谈python的深浅拷贝以及fromkeys的用法
Mar 08 Python
利用Python实现手机短信监控通知的方法
Jul 22 Python
python opencv将图片转为灰度图的方法示例
Jul 31 Python
OpenCV哈里斯(Harris)角点检测的实现
Jan 15 Python
使用TensorFlow对图像进行随机旋转的实现示例
Jan 20 Python
python数据预处理 :数据共线性处理详解
Feb 24 Python
python 6行代码制作月历生成器
Sep 18 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版本实现代码
2012/09/15 PHP
ThinkPHP3.1之D方法实例详解
2014/06/20 PHP
php利用array_search与array_column实现二维数组查找
2019/07/08 PHP
用JavaScript页面不刷新时全选择,全删除(GridView)
2009/04/14 Javascript
一些主流JS框架中DOMReady事件的实现小结
2011/02/12 Javascript
js网页侧边随页面滚动广告效果实现
2011/04/14 Javascript
JavaScript判断一个URL链接是否有效的实现方法
2011/10/08 Javascript
jQuery代码优化 遍历篇
2011/11/01 Javascript
根据IP的地址,区分不同的地区,查看不同的网站页面的js代码
2013/02/26 Javascript
Javascript new Date().valueOf()的作用与时间戳由来详解
2013/04/24 Javascript
javascript使用输出语句实现网页特效代码
2015/08/06 Javascript
深入浅析Bootstrap列表组组件
2016/05/03 Javascript
Jquery调用iframe父页面中的元素及方法
2016/08/23 Javascript
jQuery动态添加.active 实现导航效果代码思路详解
2017/08/29 jQuery
Node之简单的前后端交互(实例讲解)
2017/11/14 Javascript
Vue表单绑定的实例代码(单选按钮,选择框(单选时,多选时,用 v-for 渲染的动态选项)
2019/05/13 Javascript
Vue修改项目启动端口号方法
2019/11/07 Javascript
Vue中点击active并第一个默认选中功能的实现
2020/02/24 Javascript
[01:45]亚洲邀请赛互动指南虚拟物品介绍
2015/01/30 DOTA
Python标准库之sqlite3使用实例
2014/11/25 Python
Python实现的字典值比较功能示例
2018/01/08 Python
TensorFlow入门使用 tf.train.Saver()保存模型
2018/04/24 Python
Python基于生成器迭代实现的八皇后问题示例
2018/05/23 Python
python实现批量视频分帧、保存视频帧
2019/05/31 Python
Python常用数据分析模块原理解析
2020/07/20 Python
关于python中导入文件到list的问题
2020/10/31 Python
世界上获奖最多的手机镜头:Olloclip
2018/03/03 全球购物
c/c++某大公司的两道笔试题
2014/02/02 面试题
九年级家长会邀请函
2014/01/15 职场文书
2014基层党员干部学习全国两会心得体会
2014/03/17 职场文书
优秀公益广告词大全
2014/03/19 职场文书
关于梦想的演讲稿
2014/05/05 职场文书
大专学生求职自荐信
2014/07/06 职场文书
责任书范本
2014/08/25 职场文书
接待员岗位职责
2015/02/13 职场文书
MySQL自定义函数及触发器
2022/08/05 MySQL