54

协程的概念听起来很有趣,但我不知道,在真正的生产环境中是否有意义?协程的用例是什么,协程实现比其他方法更优雅、更简单或更高效?

4

7 回答 7

53

一个用例是具有多个同时连接的 Web 服务器,需要安排与所有连接并行的读取和写入。

这可以使用协程来实现。每个连接都是一个协同程序,它读取/写入一些数据,然后将控制权交给调度程序。调度程序传递到下一个协程(它做同样的事情),循环遍历所有连接。

于 2008-11-20T00:00:42.267 回答
32

用例:协程通常在游戏编程中用于时间片计算。

为了在游戏中保持一致的帧速率,例如 60 fps,您有大约 16.6 毫秒的时间来执行每一帧中的代码。这包括物理模拟、输入处理、绘图/绘画。

假设您的方法在每一帧中执行。如果您的方法需要很长时间并且最终跨越多个帧,那么您将在游戏循环中错开其余的计算,这会导致用户看到“卡顿”(帧速率突然下降)。

协程可以对计算进行时间切片,以便它在每一帧中运行一点点。

为此,协程允许该方法将计算“让给”回“调用者”(在本例中为游戏循环),以便下次调用该方法时,它会从中断的地方恢复。

于 2013-09-26T16:39:58.733 回答
25

Unix管道是一个用例:

grep TODO *.c | wc -l

上面的管道是一个协程。该grep命令生成一系列行并将它们写入缓冲区。该wc命令从缓冲区中读取这些行。如果缓冲区填满,则grep“阻塞”直到缓冲区清空。如果缓冲区为空,则wc等待缓冲区中的更多输入。

协程更常用于更受约束的模式中,例如提到的 Python 生成器,或用作管道。

有关更多详细信息和示例,请阅读 Wikipedia 文章,尤其是coroutinesiterators

于 2008-11-20T03:26:43.710 回答
20

真正的协程需要语言支持。它们需要由编译器实现并得到底层框架的支持。

协程的一种语言支持的实现是 C# 2.0yield return关键字,它允许您编写一个返回多个值以进行循环的方法。

但是,yield return确实有局限性。该实现使用辅助类来捕获状态,并且它仅支持协程作为生成器(迭代器)的特定情况。

在更一般的情况下,协程的一个优点是它们使某些基于状态的计算更容易表达和理解。例如,将状态机实现为一组协程可能比其他实现更优雅。但这样做需要 C# 或 Java 中尚不存在的语言支持。

于 2008-11-19T23:23:57.817 回答
15

协程对于实现生产者/消费者模式很有用。

例如,Python 在名为generators的语言特性中引入了协程,旨在简化迭代器的实现。

它们对于实现协作多任务也很有用,其中每个任务都是一个协程,可以让给调度程序/反应器。

于 2008-11-19T23:31:14.170 回答
11

当系统执行两个或多个任务时,协程可能很有用,这些任务最自然地被描述为一系列涉及大量等待的长时间运行的步骤。

例如,考虑具有 LCD 和键盘用户界面和调制解调器的设备,它需要使用调制解调器定期调用和报告其状态,而与键盘上的用户正在做什么无关。编写用户界面的最佳方式可能是使用诸如“input_numeric_value(&CONV_SPEED_FORMAT, &conveyor_speed);”之类的函数。当用户输入一个值时它会返回,处理通信的最好方法可能是使用像“wait_for_carrier();”这样的函数 当设备已连接或确定它不会连接时,它将返回。

如果没有协程,UI 子系统或调制解调器子系统都必须使用状态机来实现。使用协程可以让两个子系统都以最自然的方式编写。请注意,重要的是,任何子系统都不会在不将事物置于“一致”状态并调用yield()的情况下运行很长时间,也不会在不首先将事物置于“一致”状态的情况下调用yield(),但通常不难满足那些约束。

请注意,虽然可以使用成熟的多任务处理,但几乎在任何共享状态发生更改的地方都需要广泛使用锁或其他互斥结构。由于协程切换器除了在 yield() 调用之外永远不会切换任何东西,因此任何一个例程都可以自由地改变共享状态,只要它确保在下一个 yield 之前一切都井然有序,并准备好让另一个例程改变状态“在“产量()期间。

于 2010-07-14T15:52:35.087 回答
7

作为一个生产者/消费者的例子,一个批处理报告程序是用协程实现的。

该示例的关键提示是消耗输入数据的重要工作(例如解析数据或在帐户上累积费用和付款),以及产生输出的重要工作。当你具备这些特征时,那么:

  • 如果您可以在不同的地方编写工作单元,则很容易组织/理解输入端代码。
  • 如果输出端代码可以读取嵌套控制结构中的下一个工作单元,则同样易于组织/理解输出端代码。

那么协程和队列都是可供您使用的好技术。

于 2009-02-04T18:20:32.980 回答