它只是做它運行的工作,如果你使用的是類POSIX平臺。如果您使用的是Windows,則每個進程都會以完全不同的鎖副本結束。
class ParentApp():
mutex=Lock()
def report(self,msg):
print("\nGETTING for {}".format(msg))
with self.mutex:
print("GOT for {}".format(msg))
sys.stdout.write(msg)
sys.stdout.flush()
time.sleep(5)
在Linux上:
GETTING for BLABLA
GOT for BLABLA
BLABLA
GETTING for TESTTEST
< 5 second delay here>
在Windows上:
GETTING for BLABLA
GOT for BLABLA
BLABLA
GETTING for TESTTEST
GOT for TESTTEST
TESTTEST
<5 second delay here>
這是因爲Posix的
您可以通過添加一些額外的跟蹤和sleep
聲明見本平臺使用os.fork()
創建新進程,這意味着您在父進程中創建的會自動由子代繼承。但是,Windows沒有os.fork
,所以需要產生一個新進程,然後將模塊重新導入到子進程中。重新導入模塊意味着ParentApp
被重新導入並重新執行,Lock
類屬性也被重新導入並重新執行。所以,你的父母和兩個孩子最終都會擁有自己獨特的Lock
。
要解決這個問題,您需要在父項中創建一個Lock
,並將其傳遞給子項。實際上,對於您當前的體系結構來說,這不是一項簡單的任務 - 您將Lock
對象作爲參數傳遞給pool.map
,這將不允許您傳遞Lock
對象。如果你嘗試它,你會得到一個異常:
RuntimeError: Lock objects should only be shared between processes through inheritance
只能在點通過正常Lock
對象爲兒童,你實際上是開始一個Process
。一旦他們開始(像他們,當你調用一個Pool
方法),你會得到異常:
l = Lock()
p = Process(target=func, args=(l,)) # ok
p.start()
pool = Pool()
pool.apply(func, args=(l,)) # not ok, raises an exception.
爲了傳遞一個Lock
像map
一個Pool
功能,你需要使用一個multiprocessing.Manager
創建共享鎖。下面是我建議做:
import sys
from multiprocessing import Pool, Lock, get_context, Manager
import time
class ParentApp():
def __init__(self, mutex):
self.mutex = mutex
def report(self,msg):
with self.mutex:
sys.stdout.write(msg)
class ChildApp1(ParentApp):
def print_report(self):
for i in range(100):
ParentApp.report(self, 'BLABLA')
class ChildApp2(ParentApp):
def print_report(self):
for i in range(100):
ParentApp.report(self, 'TESTTEST')
def runnable(app):
app.print_report()
def main():
apps=[]
m = Manager()
lock = m.Lock()
apps.append(ChildApp1(lock))
apps.append(ChildApp2(lock))
pool = Pool(len(apps))
pool.map(runnable, apps)
if __name__ == '__main__':
sys.exit(main())
爲了確保Lock
是共享的,我們需要有ParentApp
採取實際鎖定對象作爲參數。這不是一件好事,因爲它在課堂上完全獨立,但我認爲這是我們可以用Windows的侷限性做的最好的。
這是,運行它:)也請讓我知道這段代碼中有什麼奇怪的,也許這是我的問題的根源 – Kam 2014-09-03 20:26:46
你期望它做什麼工作?在每個報告的末尾添加一個換行符,然後再次運行。 – 2014-09-03 20:27:45
@Kam你粘貼的代碼絕對不會運行。 'if __main__ ==「__main __」'應該是'if __name__ =='__main __「',並且您在'app'和'apps'之間切換您的對象列表。 – dano 2014-09-03 20:29:44