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


当前回答

另一方面, 在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