探究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实现获取序列中最小的几个元素
Sep 25 Python
Python读写ini文件的方法
May 28 Python
Django 导出 Excel 代码的实例详解
Aug 11 Python
Python中import机制详解
Nov 14 Python
python GUI实例学习
Nov 21 Python
Python的SimpleHTTPServer模块用处及使用方法简介
Jan 22 Python
Python实现读写INI配置文件的方法示例
Jun 09 Python
使用pygame写一个古诗词填空通关游戏
Dec 03 Python
Python获取二维数组的行列数的2种方法
Feb 11 Python
Pyinstaller加密打包应用的示例代码
Jun 11 Python
Python Excel vlookup函数实现过程解析
Jun 22 Python
python数字图像处理:图像简单滤波
Jun 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实现基于图的深度优先遍历输出1,2,3...n的全排列功能
2017/11/10 PHP
搜索附近的人PHP实现代码
2018/02/11 PHP
Laravel框架自定义公共函数的引入操作示例
2019/04/16 PHP
PHP实现微信提现功能(微信商城)
2019/11/21 PHP
JavaScript 学习 - 提高篇
2007/02/02 Javascript
html组件不可输入(只读)同时任何组件都有效
2013/04/01 Javascript
js实现的点击数量加一可操作数据库
2014/05/09 Javascript
使用node.js 制作网站前台后台
2014/11/13 Javascript
ztree获取选中节点时不能进入可视区域出现BUG如何解决
2015/12/03 Javascript
node.js中 stream使用教程
2016/08/28 Javascript
Nodejs实现短信验证码功能
2017/02/09 NodeJs
详解AngularJs路由之Ui-router-resolve(预加载)
2017/06/13 Javascript
Node.js创建Web、TCP服务器
2017/12/05 Javascript
JavaScript模板引擎应用场景及实现原理详解
2018/12/14 Javascript
原生js实现公告滚动效果
2021/01/10 Javascript
小程序实现上下移动切换位置
2019/09/23 Javascript
JavaScript canvas基于数组生成柱状图代码实例
2020/03/06 Javascript
javascript设计模式 ? 代理模式原理与用法实例分析
2020/04/16 Javascript
Vue实现简易购物车页面
2020/12/30 Vue.js
[03:11]2014DOTA2国际邀请赛-VG掉入败者组 独家专访357
2014/07/19 DOTA
[01:34]DAC2018主赛事第四日五佳镜头 Gh巨牙海民助Miracle-死里逃生
2018/04/07 DOTA
[01:04:39]OG vs Mineski 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
pandas使用get_dummies进行one-hot编码的方法
2018/07/10 Python
Python Pexpect库的简单使用方法
2019/01/29 Python
Python在终端通过pip安装好包以后在Pycharm中依然无法使用的问题(三种解决方案)
2020/03/10 Python
浅谈keras使用预训练模型vgg16分类,损失和准确度不变
2020/07/02 Python
如何用python批量调整视频声音
2020/12/22 Python
咨询公司各岗位职责
2013/12/02 职场文书
外语系毕业生自荐信范文
2013/12/16 职场文书
促销活动计划书
2014/05/02 职场文书
学习三严三实心得体会
2014/10/13 职场文书
2015年中秋节演讲稿
2015/03/20 职场文书
2016年政治理论学习心得体会
2016/01/25 职场文书
分家协议书范本
2016/03/22 职场文书
一文读懂navicat for mysql基础知识
2021/05/31 MySQL
如何用六步教会你使用python爬虫爬取数据
2022/04/06 Python