我应该使用fork还是线程?

8
在我的脚本中,我有一个名为foo函数的功能。它基本上使用pynotify来在一段时间间隔(比如15分钟)后重复地通知用户有关某些事情。
def foo:
    while True:
        """Does something"""
        time.sleep(900)

我的主要脚本必须与用户交互并完成所有其他事情,因此我不能直接调用foo()函数。

有什么更好的方法可以做到这一点以及为什么?使用fork还是线程?


哦,两个相互矛盾的答案... - kennytm
@Kenny TM:不足为奇。问题中没有定义“更好”。此外,对于大多数“更好”的定义,这是非常有争议的。 - S.Lott
5个回答

9

我不会告诉你该使用哪种,但下面是每种的一些优点:

线程比进程更快地启动,并且线程使用的操作系统资源较少,包括内存、文件句柄等。 线程还提供了通过共享变量进行通信的选项(尽管许多人认为这更像是一个缺点而非优点-请参见下文)。

进程各自拥有独立的内存和变量,这意味着进程通常通过相互发送消息来进行通信。 这比通过共享内存进行线程通信更容易实现正确性。 进程也可以真正并发地运行,因此如果您有多个CPU核心,则可以使用进程使它们保持繁忙状态。 在Python*中,全局解释器锁定会阻止线程在多个核上运行。


* - 即CPython,这是您到http://python.org下载Python时获得的Python实现。 其他Python实现(如Jython)不一定禁止Python同时在多个CPU上运行线程。 感谢@EOL进行澄清。


我使用线程,因为任务不需要占用大量CPU资源。同时,我没有使用fork,因为创建一个全新的PCB的速度较慢。 - shadyabhi
3
你可能是指“在CPython中,全局解释器锁……”。事实上,在其他一些Python实现(如Jython、Iron Python等)中没有GIL。 - Eric O. Lebigot
@EOL - 确实如此。我假设提问者正在使用CPython,因为人们通常会说明他们是否使用*Cython以外的任何东西。不过,我已经接受了你的意见 - 我会更新我的答案。 - Joe Carnahan

4

对于这种问题,线程和进程似乎都不是正确的方法。如果你只想每15分钟通知用户某些事情,为什么不使用像GLib或Twisted的反应堆那样的事件循环呢?这可以让你安排一些应该定期运行的操作,并继续进行程序的其余部分。


我是一个初学者,所以我不知道如何实现它。但是,你的答案似乎很有说服力... - shadyabhi

4
使用多进程可以同时利用多个CPU核心,而在CPython中使用线程不能这样做(线程轮流使用单个CPU核心),因此,如果您有CPU密集型工作并且绝对想使用线程,则应考虑Jython或IronPython。对于CPython来说,这一点经常足以使选择倾向于"multiprocessing"模块而不是"threading"模块(它们提供的接口非常相似,因为"multiprocessing"被设计为很容易取代"threading")。
除了这个关键的考虑因素之外,在Windows上,线程通常(从性能角度)更好(因为在那里创建新进程是一个沉重的任务),但在Unix变体(Linux、BSD版本、OpenSolaris、MacOSX等)上却不那么常见,因为在那里创建新进程更快(但如果您使用IronPython或Jython,请在您所关心的平台上检查,看看这在相关的虚拟机中是否仍然适用——对于IronPython,.NET或Mono使用CLR,对于Jython,使用您选择的JVM)。

3
进程非常简单。只需释放它们,让操作系统处理即可。
此外,进程通常更加高效。进程不共享I/O资源池,它们是完全独立的。
Python的subprocess.Popen可以处理所有事情。

我点赞了!S. Lott在Python方面比我更有权威性。 - duffymo

1
如果您说的是 os.fork,那我建议不要使用它。它不跨平台而且过于底层 - 您需要自己实现进程之间的通信。
如果您想使用一个独立的进程,则可以使用 subprocess 模块,或者如果您使用的是 Python 2.6 或更高版本,则可以使用新的 multiprocessing 模块。它具有非常类似于 threading 模块的 API,因此您可以开始使用线程,然后轻松地切换到进程,反之亦然。
对于您想做的事情,我认为应该使用线程,除非“做某事”的任务很耗费 CPU 资源,并且您想利用多个核心,但我在这种情况下认为不太可能。

如果我有CPU密集型任务,我应该选择哪些处理器?为什么? - shadyabhi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接