协程只是完成处理程序周围的语法糖吗?

Are coroutines just syntactic sugar around completion handlers?

协程是否只是完成块周围的语法糖并且将在幕后创建完成块?或者协程的概念比编译器技巧更复杂和广泛得多,也就是语法糖

这不仅仅是语法糖,一点也不是。协程不阻塞线程,它们只是暂停执行,因此它们鼓励非阻塞并发编程。

协程不依赖于操作系统或 JVM 的特性(例如,它们不映射到本机线程)。相反,协程和 suspend 函数特别由编译器进行转换,生成一个 状态机 ,能够处理一般的挂起并传递挂起的协程以保持其状态。这是由 Continuations 启用的,编译器将其作为参数添加到每个挂起函数;这种技术被称为“Continuation-passing style”。

详情请看https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md

这是一篇有趣的文章,提到在他们的系统中实施 async/await:http://joeduffyblog.com/2015/11/19/asynchronous-everything/

Along with this, we added the await and async keywords. A method could be marked async:

async int Foo() { ... }

All this meant was that it was allowed to await inside of it:

async int Bar() { int x = await Foo(); ... return x * x; }

Originally this was merely syntactic sugar for all the callback goop above, like it is in C#. Eventually, however, we went way beyond this, in the name of performance, and added lightweight coroutines and linked stacks.

不,协程不是语法糖。您可以将协程视为可以与调用者交互的函数。当你调用一个普通函数时,比如 foo 你将控制权传递给 foo 并且必须等到 foo 完成或抛出异常。协程是可以将控制权交还给调用者的函数,调用者可以决定协程是否应该继续以及何时如何协程应该继续。这提供了用其他语言实现特殊语言结构的机会:

  • 生成器(又名 yield 关键字)类似于 C# 和 JavaScript。当用户需要迭代器的新值时,调用者继续执行协程。协程通过调用 yield() 函数返回给调用者,该函数也将一些值传递给调用者。
  • Async/await 类似于 C# 和 JavaScript。当 Future(类似于 Task 或 Promise)得到解决时,调用者继续执行。协程通过调用 await() 函数返回给调用者。当 Future 被解析时,调用者将值传递给协程,并且协程由于 await() 调用而观察到该值。
  • Goroutines/channels 在 Go 中。

与 C#、JavaScript 或 Go 不同,Kotlin 不以特殊语法实现这些功能中的任何一个。相反,Kotlin 仅提供 suspend fun 语法,然后您可以自己实现这些功能(或从名为 kotlinx.coroutines 的相应库中获取现有功能)。

协程是异步过程的语法糖,或者更确切地说,Actor 是可重复的异步过程。