它只是做它运行的工作,如果你使用的是类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