python(一):multiprocessing——死鎖


前言
近年來,使用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
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM