探究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-基础-入门 简介
Aug 09 Python
详解Python中映射类型的内建函数和工厂函数
Aug 19 Python
Python向日志输出中添加上下文信息
May 24 Python
Django学习笔记之ORM基础教程
Mar 27 Python
python高效过滤出文件夹下指定文件名结尾的文件实例
Oct 21 Python
Django网络框架之创建虚拟开发环境操作示例
Jun 06 Python
python线程中的同步问题及解决方法
Aug 29 Python
python使用 request 发送表单数据操作示例
Sep 25 Python
keras 自定义loss损失函数,sample在loss上的加权和metric详解
May 23 Python
Pytorch转onnx、torchscript方式
May 25 Python
python中加背景音乐如何操作
Jul 19 Python
如何用python批量调整视频声音
Dec 22 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 output buffering缓存及程序缓存深入解析
2013/07/15 PHP
php解析url的三个示例
2014/01/20 PHP
php修改文件上传限制方法汇总
2015/04/07 PHP
jQuery中filter(),not(),split()使用方法
2010/07/06 Javascript
轻量级 JS ToolTip提示效果
2010/07/20 Javascript
javascript forEach通用循环遍历方法
2010/10/11 Javascript
10款非常有用的 Ajax 插件分享
2012/03/14 Javascript
关于div自适应高度/左右高度自适应一致的js代码
2013/03/22 Javascript
Egret引擎开发指南之发布项目
2014/09/03 Javascript
用js传递value默认值的示例代码
2014/09/11 Javascript
跨域资源共享 CORS 详解
2016/04/26 Javascript
BootStrap中的table实现数据填充与分页应用小结
2016/05/26 Javascript
Bootstrap模态框禁用空白处点击关闭
2016/10/20 Javascript
jQuery实现的购物车物品数量加减功能代码
2016/11/16 Javascript
Javascript中八种遍历方法的执行速度深度对比
2017/04/25 Javascript
axios异步提交表单数据的几种方法
2019/08/11 Javascript
[26:40]DOTA2上海特级锦标赛A组资格赛#1 Secret VS MVP.Phx第一局
2016/02/25 DOTA
python中二维阵列的变换实例
2014/10/09 Python
跟老齐学Python之关于类的初步认识
2014/10/11 Python
深入浅析Python中list的复制及深拷贝与浅拷贝
2018/09/03 Python
Pandas之Fillna填充缺失数据的方法
2019/06/25 Python
python+tkinter实现学生管理系统
2019/08/20 Python
Python WebSocket长连接心跳与短连接的示例
2020/11/24 Python
HTML5新表单元素_动力节点Java学院整理
2017/07/12 HTML / CSS
优秀员工自荐书
2013/12/19 职场文书
经贸日语专业个人求职信范文
2013/12/28 职场文书
中学教师请假制度
2014/02/03 职场文书
《音乐之都维也纳》教学反思
2014/04/16 职场文书
体育课课后反思
2014/04/24 职场文书
建筑结构施工求职信
2014/07/11 职场文书
大专生自我鉴定怎么写
2014/09/16 职场文书
学校总务处领导班子民主生活会对照检查材料思想汇报
2014/09/27 职场文书
详解Spring Boot使用系统参数表提升系统的灵活性
2021/06/30 Java/Android
口袋妖怪冰系十大最强精灵,几何雪花排第七,第六类似北极熊
2022/03/18 日漫
MySQL Server 层四个日志
2022/03/31 MySQL
使用Cargo工具高效创建Rust项目
2022/08/14 Javascript