什么是协程?它们与并发性有什么关系?
当前回答
另一方面, 在python中,gevent库是一个基于协程的网络库,它为您提供线程类功能,如异步网络请求,而无需创建和销毁线程的开销。所使用的协程库是绿色的。
其他回答
另一方面, 在python中,gevent库是一个基于协程的网络库,它为您提供线程类功能,如异步网络请求,而无需创建和销毁线程的开销。所使用的协程库是绿色的。
在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。由于协程之间存在依赖关系,它们必须串联运行,所以这两个协程不是并发的。
协程是Kotlin语言中可用的很棒的特性 协程是一种新的异步、非阻塞的编写方式 代码(以及更多) 协程是轻量级线程。一根轻的线就意味着它 不映射到本机线程,因此不需要上下文切换 在处理器上,所以它们更快。 它不映射到本机线程上 协程和线程都是多任务处理。但是区别在于 线程由操作系统管理,协程由用户管理。
基本上,有两种类型的协程:
Stackless Stackful
Kotlin实现了无堆栈协程-这意味着 协程没有自己的堆栈,所以它们不会映射到本机线程上。
这些是启动协程的函数:
launch{}
async{}
你可以在这里了解更多:
https://www.kotlindevelopment.com/deep-dive-coroutines/
https://blog.mindorks.com/what-are-coroutines-in-kotlin-bf4fecd476e9
协程和并发在很大程度上是正交的。协程是一种通用的控制结构,流控制在两个不同的例程之间协作传递而不返回。
Python中的'yield'语句就是一个很好的例子。它创建了一个协程。当遇到yield时,将保存函数的当前状态,并将控制返回给调用函数。然后,调用函数可以将执行转移回屈服函数,它的状态将恢复到遇到“屈服”的位置,并继续执行。
Kotlin 协程
[同步与异步]
[并发vs并行]
通常我们认为协程是轻量级线程,它们允许我们以同步的方式编写异步的、非阻塞的代码
至于Kotlin协程:
协程是一个合成糖/附加层,它允许你以非阻塞的方式运行任务,没有回调。协程由以下组件组成:
延续 作业-管理程序和保存它的状态 CoroutineScope(包含作业和Xontext)——处理作业组(层次结构)并管理它们(启动和取消) Dispatcher -用于处理线程池- Main, IO, Default… 上下文-像Map这样的数据结构,以保存一些日期,如Job, Dispatcher和自定义数据
让我们回顾一些例子
class MyClass {
val network = Network()
val fileSystem = FileSystem()
suspend fun downloadFile(): File {
//suspendCoroutine is key point
return suspendCoroutine { continuation ->
network.download(callback: Network.Callback {
override fun onSuccess(file: File) {
continuation.resume(file)
}
})
}
}
suspend fun saveFile(file: File) {
//suspendCoroutine is key point
return suspendCoroutine { continuation ->
fileSystem.save(callback: FileSystem.Callback {
override fun onSuccess() {
continuation.resume()
}
})
}
}
GlobalScope.launch {
val downloadResult = downloadFile() //1. suspend function
show(downloadResult) //2. UI
saveFile(downloadResult) //3. suspend function
}
延续
它创建了Continuation类,它是一个状态机,内部有invokeSuspend()函数。在任何挂起函数的末尾调用invokeSuspend()(像回调一样)
class Continuation {
int label;
//block of local variabels
File file;
void invokeSuspend(Object result) {
switch (label) {
case 0: {
label = 1;
downloadFile(this); //1. suspend function
return;
}
case 1: {
file = (File) result; //work with result
show(file); //2. UI
saveFile(file, this); //3.suspend function
return;
}
}
}
}
class MyClass {
fun downloadFile(continuation: Continuation): File {
//logic
continuation.invokeSuspend(file)
}
fun saveFile(file: File, continuation: Continuation) {
//logic
continuation.invokeSuspend()
}
}
暂停
suspended只是一个函数的标记,它将被添加新的延续参数(continue: continue) 分割状态机,这意味着它可以暂停机器 暂停函数应该在Continuation.resume() -> Continuation. invokesuspend()中调用Continuation.resume() 挂起的函数只能从couroutine调用
协程的行为完全依赖于库的实现