【问题标题】:reactor design pattern in a single thread vs multiple threads单线程与多线程中的反应器设计模式
【发布时间】:2014-11-09 12:30:35
【问题描述】:
我一直在阅读有关反应器设计模式的文章,特别是在 Python Twisted 网络框架的上下文中。我对反应器设计的简单理解是,有一个线程会坐下来等待一个或多个 I/O 源(或文件描述符)可用,然后它将同步循环遍历每个源,执行任何回调为这些来源中的每一个指定。这确实意味着如果任何回调本身阻塞,整个程序都会阻塞。无论如何,一旦所有回调都执行完毕,反应器就会返回等待更多 I/O 源准备就绪。
与在它们出现时异步循环通过每个源(即为每个源启动单独的线程)相比,这样做的优点和缺点是什么。我想如果您的所有回调都非常快,这可能会降低效率,因为操作系统现在必须处理管理多个线程并在它们之间进行交换。但是现在似乎不可能阻止主程序,并且作为一个额外的好处,主反应器可以继续监听源。简而言之,为什么像 Twisted 这样的东西不这样做,而是保持单线程模型?
【问题讨论】:
标签:
python
multithreading
twisted
reactor
【解决方案1】:
与在出现时异步循环通过每个源(即为每个源启动单独的线程)相比,这样做的优点和缺点是什么。
您所描述的基本上是在使用阻塞 I/O API 的多线程程序中发生的情况。在这种情况下,“反应器”移入内核,“异步循环”是内核完成一些未完成的阻塞操作,释放用户空间线程以继续。
与严格的单线程方法相比,这种方法的缺点是在线程安全(即正确性)方面的复杂性大大增加。
优点是可以更好地利用多个 CPU(但运行多个单线程事件驱动进程通常也能提供此好处)以及更多熟悉和熟悉多线程方法的程序员(尽管通常是错误的)并发。
不过,与此相关的还有 PyPy 团队在提供比传统多线程模型更好的抽象方面所做的努力。 PyPy 在软件事务内存 (STM) 方面的工作可以提供一个系统,在该系统中,工作被异步分派给多个工作线程,而不会违反在严格的单线程系统中有效的假设。如果这行得通,它可以提供两全其美的效果。
【解决方案2】:
但是现在好像不能屏蔽主程序了,
我不是 Python 人,但我在 Boost 的上下文中完成了这项工作。阿西奥。你是对的——你的回调需要快速执行并将控制权返回给主反应器。这个想法是只在你的回调中使用异步调用。例如,您不会使用 API 发送阻止并返回状态代码的 IP 数据报。相反,您将使用注册成功和失败回调的非阻塞 API。这让调用发送调用立即返回。一旦操作系统处理完数据包,反应器就会调用成功/失败回调。