前言
近年来,使用python的人越来越多,这得益于其清晰的语法、低廉的入门代价等因素。尽管python受到的关注日益增多,但python并非完美,例如被人诟病最多的GIL(值得注意的是,GIL并非python特性,它是在实现Python解析器(CPython)时所引入的一个概念,而CPython是大部分环境下默认的Python执行环境),全称Global Interpreter Lock。从官方定义来看,GIL无疑就是一把全局排他锁,会严重影响python多线程的效率,甚至几乎等于Python是个单线程程序。

为了满足开发者的需求,python社区推出了multiprocessing。顾名思义,multiprocessing使用了多进程而不是多线程,每个进程有自己的独立的GIL,因此也不会出现进程之间的GIL争抢。当然multiprocessing也并非完美,例如增加了数据通讯的难度等方面。讲了这么多背景,下面分享一下使用multiprocessing踩过的坑。由于这篇博客偏向实际工程,主要分享应用经验,相关基础知识可以查阅Python Documentation。

系统
>>> import sys
>>> print(sys.version)
3.6.0 |Anaconda 4.3.1 (64-bit)| (default, Dec 23 2016, 12:22:00) \n[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]
1
2
3
死锁
百度百科对死锁的定义

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程1。

从定义可知,永远互相等待是死锁的一个重要特征。在multiprocessing中,你稍不留神,也会犯这种错误,例如:

from multiprocessing import Process, Queue

def f(q):
q.put('X' * 1000000)

if __name__ == '__main__':
queue = Queue()
p = Process(target=f, args=(queue,))
p.start()
p.join() # this deadlocks
1
2
3
4
5
6
7
8
9
10
结果是死锁。当一个进程被join时,Python会检查被放入Queue中的数据是否已经全部删除(例如Queue.get),若没有删除,则进程会一直处于等待状态。发现这种情况时,一方面感叹“你让我找的好苦啊”,另一方面思考python的开发者怎么会对这种情况坐视不理呢?是否做了某些尝试?例如若Queue小于某个阈值,进程join会将其视为空Queue。基于这种猜想,做了以下实验

from multiprocessing import Process, Queue
import time

def f(q):
num = 10000
q.put('X' * num)
print("Finish put....")

if __name__ == '__main__':
queue = Queue()
p = Process(target=f, args=(queue,))
p.start()
print("Start to sleep...")
time.sleep(2)
print("Wake up....")
p.join()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
结果是程序正常结束,一定程度上验证了我的猜想。为了进一步确定猜想的正确性,我又做了num=1000、num=100和num=1的实验,结果均是程序正常结束,证明进程join时的确会判断Queue的大小,从而避免死锁。尽管这种策略有一定效果,但并不能根治死锁,所以进程join时一定要保证Queue中数据已经被全部取走。

除了上述的情况外,进程join自身、终止带锁的进程等情况也会导致死锁,以后会慢慢分享给大家。

结语
尽管multiprocessing对死锁有一定的容错能力,但并不完善,优化代码才是正道。
---------------------
作者:cptu
来源:CSDN
原文:https://blog.csdn.net/AckClinkz/article/details/78409301
版权声明:本文为博主原创文章,转载请附上博文链接!

python(一):multiprocessing——死锁的更多相关文章

  1. python之multiprocessing创建进程

    python的multiprocessing模块是用来创建多进程的,下面对multiprocessing总结一下使用记录. multiprocessing创建多进程在windows和linux系统下的 ...

  2. python中multiprocessing.pool函数介绍_正在拉磨_新浪博客

    python中multiprocessing.pool函数介绍_正在拉磨_新浪博客     python中multiprocessing.pool函数介绍    (2010-06-10 03:46:5 ...

  3. python的multiprocessing模块进程创建、资源回收-Process,Pool

    python的multiprocessing有两种创建进程的方式,每种创建方式和进程资源的回收都不太相同,下面分别针对Process,Pool及系统自带的fork三种进程分析. 1.方式一:fork( ...

  4. python多进程-----multiprocessing包

    multiprocessing并非是python的一个模块,而是python中多进程管理的一个包,在学习的时候可以与threading这个模块作类比,正如我们在上一篇转载的文章中所提,python的多 ...

  5. python多进程(multiprocessing)

    最近有个小课题,需要用到双进程,翻了些资料,还算圆满完成任务.记录一下~ 1.简单地双进程启动 同时的调用print1()和print2()两个打印函数,代码如下: #/usr/bin/python ...

  6. Python使用multiprocessing实现一个最简单的分布式作业调度系统

    Python使用multiprocessing实现一个最简单的分布式作业调度系统介绍Python的multiprocessing模块不但支持多进程,其中managers子模块还支持把多进程分布到多台机 ...

  7. python 使用multiprocessing需要注意的问题

    我们在编写程序的时候经常喜欢这样写代码 import MySQLdb import time from multiprocessing import Process conn = MySQLdb.co ...

  8. python多进程multiprocessing Pool相关问题

    python多进程想必大部分人都用到过,可以充分利用多核CPU让代码效率更高效. 我们看看multiprocessing.pool.Pool.map的官方用法 map(func, iterable[, ...

  9. Shared variable in python's multiprocessing

    Shared variable in python's multiprocessing https://www.programcreek.com/python/example/58176/multip ...

  10. python下multiprocessing和gevent的组合使用

    python下multiprocessing和gevent的组合使用 对于有些人来说Gevent和multiprocessing组合在一起使用算是个又高大上又奇葩的工作模式. Python的多线程受制 ...

随机推荐

  1. Volley 源码解析 StringRequest解析

    Android Vollety是一个很有用的框架,所以想借鉴前人思想,分析这个源代码. 参考: http://blog.csdn.net/crazy__chen/article/details/464 ...

  2. 深究Spring中Bean的生命周期

    前言 这其实是一道面试题,是我在面试百度的时候被问到的,当时没有答出来(因为自己真的很菜),后来在网上寻找答案,看到也是一头雾水,直到看到了<Spring in action>这本书,书上 ...

  3. Centos常用命名

    1.关机 (系统的关机.重启以及登出 ) 的命令 shutdown -h now 关闭系统(1) init 0 关闭系统(2) telinit 0 关闭系统(3) shutdown -h hours: ...

  4. 局域网Cesium离线影像及瓦片影像地图加载

    1.Cesium简介 优点: cesium展示地图数据效果比较好,解析2D地图各种不同服务类型的数据源,比如百度地图.天地图.arcgis地图.BingMap.openStreetMap.MapBox ...

  5. LazyTableImages范例解析

    近来想了解iPhone的多线程处理,查阅到了官方范例LazyTableImages,发现代码中有不仅有多线程处理,还有XML解析和异步下载图片,感觉官方例子真是全面啊,便花了时间好好研究下. Lazy ...

  6. HDU - 4630 No Pain No Game (线段树 + 离线处理)

    id=45786" style="color:blue; text-decoration:none">HDU - 4630 id=45786" style ...

  7. sqlfairy用法

    要画一个数据库的ER图,我比较懒,就想用工具来生成. 找了一下,发现一个不错的工具,名字叫sal-fairy 很强大,可以有很多用处. 其中有一个命令sqlt-graph,可以完成生成ER图. 用法如 ...

  8. [转]Linux上程序执行的入口--Main

    main()函数,想必大家都不陌生了,从刚开始写程序的时候,大家便开始写main(),我们都知道main是程序的入口.那main作为一个函数,又是谁调用的它,它是怎么被调用的,返回给谁,返回的又是什么 ...

  9. Golang Global Variable access

    golang 中全局变量的问题. ------------------------------------------------------------------ 17down votefavor ...

  10. [LeetCode][Java] Container With Most Water

    题目: Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, a ...