什么是协程?它们与并发性有什么关系?


当前回答

协程和并发在很大程度上是正交的。协程是一种通用的控制结构,流控制在两个不同的例程之间协作传递而不返回。

Python中的'yield'语句就是一个很好的例子。它创建了一个协程。当遇到yield时,将保存函数的当前状态,并将控制返回给调用函数。然后,调用函数可以将执行转移回屈服函数,它的状态将恢复到遇到“屈服”的位置,并继续执行。

其他回答

协程和并发在很大程度上是正交的。协程是一种通用的控制结构,流控制在两个不同的例程之间协作传递而不返回。

Python中的'yield'语句就是一个很好的例子。它创建了一个协程。当遇到yield时,将保存函数的当前状态,并将控制返回给调用函数。然后,调用函数可以将执行转移回屈服函数,它的状态将恢复到遇到“屈服”的位置,并继续执行。

协程作为并发性的实现和多线程的替代方案。

协程是实现并发的单线程解决方案。

         A-Start ------------------------------------------ A-End   
           | B-Start -----------------------------------------|--- B-End   
           |    |      C-Start ------------------- C-End      |      |   
           |    |       |                           |         |      |
           V    V       V                           V         V      V      
1 thread->|<-A-|<--B---|<-C-|-A-|-C-|--A--|-B-|--C-->|---A---->|--B-->| 

与多线程解决方案相比:

thread A->|<--A|          |--A-->|
thread B------>|<--B|            |--B-->|
thread C ---------->|<---C|             |C--->|

协程是异步编程的一种实现,异步编程用于实现并发。 许多语言使用协程实现异步编程。其他答案表明Python, Kotlin, Lua, c++已经做到了。 最有用/通常用于涉及I/O绑定问题的场景,例如在获取数据时呈现UI,或从多个数据源下载。

在Lua编程中,“协程”部分:

A coroutine is similar to a thread (in the sense of multithreading): it is a line of execution, with its own stack, its own local variables, and its own instruction pointer; but it shares global variables and mostly anything else with other coroutines. The main difference between threads and coroutines is that, conceptually (or literally, in a multiprocessor machine), a program with threads runs several threads in parallel. Coroutines, on the other hand, are collaborative: at any given time, a program with coroutines is running only one of its coroutines, and this running coroutine suspends its execution only when it explicitly requests to be suspended.

所以关键是:协程是“协作的”。即使在多核系统中,也只有一个协程在任何给定时间运行(但多个线程可以并行运行)。协程之间存在不可抢占性,运行中的协程必须显式放弃执行。

关于“并发性”,你可以参考Rob Pike的幻灯片:

并发是独立执行计算的组合。

所以在协程A的执行过程中,它把控制权传递给了协程B。经过一段时间后,协程B又把控制权传递给了协程A。由于协程之间存在依赖关系,它们必须串联运行,所以这两个协程不是并发的。

协程类似于子例程/线程。 区别在于,一旦调用方调用了子例程/线程,它将永远不会返回到调用方函数。 但是协程可以在执行几段代码后返回到调用方,允许调用方执行一些自己的代码,并返回到它停止执行的协程点,并从那里继续。 ie。协程有多个入口点和出口点

另一方面, 在python中,gevent库是一个基于协程的网络库,它为您提供线程类功能,如异步网络请求,而无需创建和销毁线程的开销。所使用的协程库是绿色的。