探究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 相关文章推荐
解决pandas中读取中文名称的csv文件报错的问题
Jul 04 Python
pandas 将索引值相加的方法
Nov 15 Python
python的常用模块之collections模块详解
Dec 06 Python
Python函数和模块的使用总结
May 20 Python
python 随机生成10位数密码的实现代码
Jun 27 Python
python 求定积分和不定积分示例
Nov 20 Python
numpy.ndarray 实现对特定行或列取值
Dec 05 Python
没编程基础可以学python吗
Jun 17 Python
python中format函数如何使用
Jun 22 Python
python matplotlib工具栏源码探析三之添加、删除自定义工具项的案例详解
Feb 25 Python
python 利用PyAutoGUI快速构建自动化操作脚本
May 31 Python
Python利用FlashText算法实现替换字符串
Mar 31 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
windows下PHP APACHE MYSQ完整配置
2007/01/02 PHP
PHP实现邮件群发的源码
2013/06/18 PHP
Yii查询生成器(Query Builder)用法实例教程
2014/09/04 PHP
php使用MySQL保存session会话的方法
2015/06/18 PHP
CodeIgniter读写分离实现方法详解
2016/01/20 PHP
php中简单的对称加密算法实现
2017/01/05 PHP
JavaScript数据类型之基本类型和引用类型的值
2015/04/01 Javascript
AngularJS自定义服务与fliter的混合使用
2016/11/24 Javascript
Node.js连接MongoDB数据库产生的问题
2017/02/08 Javascript
微信小程序实现实时圆形进度条的方法示例
2017/02/24 Javascript
jQuery插件HighCharts绘制简单2D折线图效果示例【附demo源码】
2017/03/21 jQuery
Bootstrap页面标题Page Header的实现方法
2017/03/22 Javascript
JS实现方形抽奖效果
2018/08/27 Javascript
vue-cli设置publicPath小记
2020/04/14 Javascript
解决Vue-cli3没有vue.config.js文件夹及配置vue项目域名的问题
2020/12/04 Vue.js
深入理解Python3 内置函数大全
2017/11/23 Python
Python与人工神经网络:使用神经网络识别手写图像介绍
2017/12/19 Python
浅析python中的迭代与迭代对象
2018/10/08 Python
基于Python实现定时自动给微信好友发送天气预报
2018/10/25 Python
Python中作用域的深入讲解
2018/12/10 Python
Python操作redis实例小结【String、Hash、List、Set等】
2019/05/16 Python
pytorch+lstm实现的pos示例
2020/01/14 Python
python手写均值滤波
2020/02/19 Python
keras自动编码器实现系列之卷积自动编码器操作
2020/07/03 Python
python给list排序的简单方法
2020/12/10 Python
Biblibili视频投稿接口分析并以Python实现自动投稿功能
2021/02/05 Python
DVF官方网站:美国时装界尊尚品牌
2017/08/29 全球购物
行政人员工作职责
2013/12/05 职场文书
车间班组长的职责
2013/12/13 职场文书
医院检讨书范文
2014/02/01 职场文书
办公室打字员岗位职责
2014/04/16 职场文书
乡镇党建工作汇报材料
2014/10/27 职场文书
党员证明模板
2015/06/19 职场文书
新兵入伍决心书
2015/09/22 职场文书
2015年党务工作者个人工作总结
2015/10/22 职场文书
幼师必备:幼儿园期末教师评语50条
2019/11/01 职场文书