什么是协程?它们与并发性有什么关系?
当前回答
另一方面, 在python中,gevent库是一个基于协程的网络库,它为您提供线程类功能,如异步网络请求,而无需创建和销毁线程的开销。所使用的协程库是绿色的。
其他回答
我将详述@user21714的答案。协程是独立的执行路径,不能同时运行。它们依赖于一个控制器(例如python控制器库)来处理这些路径之间的切换。但是为了实现这一点,协同程序本身需要调用yield或类似的结构,以允许它们的执行暂停。
相反,线程运行在独立的计算资源上,并且彼此并行。由于它们位于不同的资源上,因此不需要调用yield来允许其他执行路径继续进行。
您可以通过启动一个多线程程序(例如jvm应用程序)来看到这种效果,其中所有八个核心i7超线程核心都被利用了:您可能会在Activity Monitor或Top中看到797%的利用率。相反,当运行一个典型的python程序(即使是带有协程或python线程的程序)时,利用率最高将达到100%。例如,一台机器超线程。
协程作为并发性的实现和多线程的替代方案。
协程是实现并发的单线程解决方案。
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,或从多个数据源下载。
另一方面, 在python中,gevent库是一个基于协程的网络库,它为您提供线程类功能,如异步网络请求,而无需创建和销毁线程的开销。所使用的协程库是绿色的。
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调用
协程的行为完全依赖于库的实现
协程是Kotlin语言中可用的很棒的特性 协程是一种新的异步、非阻塞的编写方式 代码(以及更多) 协程是轻量级线程。一根轻的线就意味着它 不映射到本机线程,因此不需要上下文切换 在处理器上,所以它们更快。 它不映射到本机线程上 协程和线程都是多任务处理。但是区别在于 线程由操作系统管理,协程由用户管理。
基本上,有两种类型的协程:
Stackless Stackful
Kotlin实现了无堆栈协程-这意味着 协程没有自己的堆栈,所以它们不会映射到本机线程上。
这些是启动协程的函数:
launch{}
async{}
你可以在这里了解更多:
https://www.kotlindevelopment.com/deep-dive-coroutines/
https://blog.mindorks.com/what-are-coroutines-in-kotlin-bf4fecd476e9