如何在python中使用多处理正确终止子进程

时间:2013-04-01 21:19:05

标签: python multiprocessing

我有几个回调函数,我想以多个进程启动,并通过来自父进程的信号终止它们。

我目前的做法是使用multiprocessing.Value创建共享c_bool并将其设置为True,然后在创建时将其分发到我的所有进程。我的进程都使用共享bool运行while循环,如下所示:

while myC_bool: ...keep running...

然后我可以将bool从父进程切换到False,所有子进程都将完成最终循环并退出。

很多人都告诉我,并且已经在文档中读到,在使用多处理时,应该尝试避免使用共享内存。 我被告知避免这种情况的最佳方法是守护进程,给它一个自定义信号处理程序并发送一个sigint / sigterm / etc ......

我的问题是,是否专门使用bool来保持循环活动,并且只是从我的父进程改变它的值,并从多个子进程中读取它是一个合适的解决方案,以使我的所有子进程快速安全地终止?我觉得所有孩子只需要查看一个共享bool就可以减少开销,而不是向他们发送x个sigints。

守护是否会成为更好的解决方案?如果是这样,我想帮助理解原因。

3 个答案:

答案 0 :(得分:9)

使用您的解决方案有很多充分的理由:

  • 比信号更容易思考。
  • 它处理的跨平台问题较少。
  • 您已经拥有以这种方式运作的代码。
  • 可以轻松添加"正常关机"机制,如果你想在将来。

......等等。

请记住,除非您能够向自己证明multiprocessing以及您所关注的每个平台上的基础操作系统原语都可以保证在没有同步的情况下工作,您需要设置{{1}每次访问共享bool时都会出现其他问题。这并不完全复杂,但是......一旦你做到了这一点,使用例如没有共享bool的Lock可能会更简单。

无论如何,如果这些都是你的理由,我会说很好,就这样做。但根据你的问题,你实际上是因为表现而选择了这个:

  

我觉得所有孩子只需要查看一个共享bool的开销就少,而不是向他们发送x个sigints

如果这是你的理由,你几乎肯定是错的。孩子们每次通过一些循环都必须查看共享bool(并获取共享锁!),而信号只需要发送给每个孩子一次。所以,你的开销几乎肯定会高得多。

但实际上,我无法想象每个子进程发送一个信号的开销,甚至每个进程每个循环都抓一次进程间锁,这在任何有用的程序中都是接近瓶颈的,所以......为什么呢?首先,这里的开销是否重要?以最简单的方式做最有意义的事情。

答案 1 :(得分:2)

由于你很谨慎修改共享变量的人,所以应该没问题。

有许多不同的解决方案可能。例如。使用multiprocessing.Event,并在设置时终止进程。 或者使用multiprocessing.Connection个对象(来自Pipe)。后者可用于父母与子女之间的双向沟通​​。就像给孩子们停下来的信号,然后向父母确认。

答案 2 :(得分:0)

告诉你“不要这样做”的人是错的。共享内存的关键是在多处理器之间共享内存,而这正是您正在做的事情。

你有一个解决方案,1)很简单,2)工作。信号/守护进程方法1)非常酷,2)更难以正确编码,3)更难理解。

我在你的方法中看到的唯一缺陷是一个进程可能会从CPU的缓存中看到bool的陈旧副本,并且在关闭时会稍微延迟。有一些方法可以刷新缓存以确保不会发生这种情况,但是您可能不需要它们,因为对于大多数应用程序来说,缓存刷新经常会自动发生。

站稳脚跟。