探究Python多進程編程下線程之間變量的共享問題
1、問題:
群中有同學(xué)貼了如下一段代碼,問為何 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 問題,然后了解多線程、多進程原理,上述問題不難回答,不過如果你不知道也沒關(guān)系,跑一下上面的代碼你就知道是什么問題了。
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 行注釋開啟,你會看到如下結(jié)果:
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[:]
結(jié)果:
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、多進程的問題遠不止這么多:數(shù)據(jù)的同步
看段簡單的代碼:一個簡單的計數(shù)器:
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
結(jié)果:
------------------------ 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
這段代碼性能如何呢?跑跑看,或者加大循環(huán)次數(shù)試一下。。。
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
相關(guān)文章
Python代碼調(diào)用執(zhí)行shell踩坑解決
這篇文章主要為大家介紹了Python代碼調(diào)用執(zhí)行shell,踩過的坑解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06
Python圖像濾波處理操作示例【基于ImageFilter類】
這篇文章主要介紹了Python圖像濾波處理操作,結(jié)合實例形式分析了Python基于ImageFilter類實現(xiàn)的濾波處理相關(guān)操作技巧,需要的朋友可以參考下2019-01-01
基于Python Numpy的數(shù)組array和矩陣matrix詳解
下面小編就為大家分享一篇基于Python Numpy的數(shù)組array和矩陣matrix詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04

