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


当前回答

在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。由于协程之间存在依赖关系,它们必须串联运行,所以这两个协程不是并发的。

其他回答

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

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

我发现这个链接的解释非常直接。这些答案中没有一个试图解释并发和并行,除了这个答案中的最后一个要点。

什么是并发(程序)?

引用自Joe Armstrong的“编程Erlang”,传奇人物:

并发程序在并行计算机上可能运行得更快。

a concurrent program is a program written in a concurrent programming language. We write concurrent programs for reasons of performance, scalability, or fault tolerance. a concurrent programming language is a language that has explicit language constructs for writing concurrent programs. These constructs are an integral part of programming language and behave the same way on all operating systems. a parallel computer is a computer that has several processing units (CPUs or cores) that can run at the same time.

所以并发性和并行性是不同的。您仍然可以在单核计算机上编写并发程序。分时调度器会让你感觉你的程序正在并发运行。

并发程序有可能在并行计算机中并行运行,但不能保证。操作系统可能只给你一个内核来运行程序。

因此,并发是一个来自并发程序的软件模型,这并不意味着您的程序可以在物理上并行运行。

协程和并发

“协程”一词由两个词组成:“co”(合作)和“routine”(函数)。

A.它实现了并发还是并行?

为了简单起见,让我们在单核计算机上讨论它。

并发性是通过来自操作系统的分时实现的。线程在CPU内核上按照指定的时间框架执行代码。它可以被OS抢占。它也可以将控制权交给操作系统。

另一方面,协程将控制权交给线程内的另一个协程,而不是交给OS。因此,线程内的所有协程仍然利用该线程的时间框架,而不会将CPU核心交给由操作系统管理的其他线程。

因此,您可以认为协程是通过用户而不是通过操作系统(或准并行)实现分时的。协程运行在分配给运行这些协程的线程的同一个核心上。

协程能实现并行吗?如果它是cpu绑定的代码,则不会。就像分时系统一样,它让你感觉它们是平行运行的,但它们的执行是交错的,而不是重叠的。如果它是IO绑定的,是的,它通过硬件(IO设备)实现并行,而不是通过您的代码。

B.与函数调用的区别?

如图所示,它不需要调用return来切换控制。它可以不计回报地付出。协程保存并共享当前函数帧(堆栈)上的状态。因此,它比函数轻量级得多,因为你不需要保存寄存器和局部变量来堆栈,并在调用ret时倒带调用stack。

我将详述@user21714的答案。协程是独立的执行路径,不能同时运行。它们依赖于一个控制器(例如python控制器库)来处理这些路径之间的切换。但是为了实现这一点,协同程序本身需要调用yield或类似的结构,以允许它们的执行暂停。

相反,线程运行在独立的计算资源上,并且彼此并行。由于它们位于不同的资源上,因此不需要调用yield来允许其他执行路径继续进行。

您可以通过启动一个多线程程序(例如jvm应用程序)来看到这种效果,其中所有八个核心i7超线程核心都被利用了:您可能会在Activity Monitor或Top中看到797%的利用率。相反,当运行一个典型的python程序(即使是带有协程或python线程的程序)时,利用率最高将达到100%。例如,一台机器超线程。

协程是Kotlin语言中可用的很棒的特性 协程是一种新的异步、非阻塞的编写方式 代码(以及更多) 协程是轻量级线程。一根轻的线就意味着它 不映射到本机线程,因此不需要上下文切换 在处理器上,所以它们更快。 它不映射到本机线程上 协程和线程都是多任务处理。但是区别在于 线程由操作系统管理,协程由用户管理。

基本上,有两种类型的协程:

Stackless Stackful

Kotlin实现了无堆栈协程-这意味着 协程没有自己的堆栈,所以它们不会映射到本机线程上。

这些是启动协程的函数:

launch{}

async{}

你可以在这里了解更多:

https://www.kotlindevelopment.com/deep-dive-coroutines/

https://blog.mindorks.com/what-are-coroutines-in-kotlin-bf4fecd476e9

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