想到我头都要炸了,还是没想明白
中文英文资料都搜了看了一些,就只是知道:
可是这明明很抽象。。。想不明白
一些语言里的 async 和 await 这种算协程吗,协程到底是个什么概念
果不其然。。。大家的回复都是那种“懂的都懂”,不懂的实在难以理解
600多天后,我还是没理解协程,而且在互联网搜索的时候又搜到了这个,悲哀。。。
1
ysc3839 2021-05-31 21:51:13 +08:00 1
你说的前两点应该描述的是有栈协程,async await 这种是无栈协程。
我没怎么了解过有栈协程。至于无栈协程,我是理解成“回调函数的语法糖”。 |
2
Jirajine 2021-05-31 21:52:06 +08:00 via Android
https://os.phil-opp.com/async-await/
看第一节语言无关的部分 |
3
Nitroethane 2021-05-31 22:17:51 +08:00 1
拿 Linux 平台上的 Go 来说明问题。
Linux 中并没有真正意义上的线程,而被叫做轻量级进程。内核源码注释中进程( process )、线程( thread )和任务( task )经常混用。 协程就是 Go 的 runtime 实现的**类似于**多线程的机制,协程的调度由 Go 的 runtime 中的协程调度器实现。当一个协程调用了阻塞操作(例如获取锁、读取的 channel 中没有数据等)时,runtime 的协程调度器会将此协程投入等待队列使其睡眠,然后调度其他处于运行队列的协程继续执行。当处于睡眠状态的协程所等待的事件发生后,调度器会唤醒并投入运行队列。 这个协程调度器是由用户态的程序 Go 自己实现的,跟内核的进程调度器完全没有关系。 |
4
ReferenceE 2021-05-31 22:39:09 +08:00 via Android
@ysc3839 async 和 await 是主要是面向 continuation 计算续集的,和协程不是一个东西
|
5
irytu 2021-05-31 23:04:47 +08:00 via iPhone
xv6 源码里读一读 swtch.S 文件里的汇编代码,一个简单的 x86 coroutine 实现
|
6
irytu 2021-05-31 23:05:23 +08:00 via iPhone 1
|
7
ysc3839 2021-05-31 23:09:17 +08:00
@ReferenceE 我不知道 stackless coroutine 在中文应该怎么翻译,但似乎大家都叫无栈协程,所以我也这么叫了。
|
8
ly841000 2021-05-31 23:24:17 +08:00
用户态调度的非抢占式轻量线程
|
9
zhangbohun 2021-05-31 23:44:21 +08:00
不完全严谨的解释,仅供参考:
线程是操作系统“调度”CPU 算力的最小单位,而所谓“调度”基本就是切换运行时的上下文数据(寄存器里的数据)然后根据 OS 的调度算法换着运行;而协程就是在更上层(比如各种语言的运行时或者工具库的实现)模拟这种暂存上下文数据并且自定义调度算法的轻量级“线程”;而 async 和 await 这个只是语法层面用于标记协程切换和调度的一种方案 |
10
GeruzoniAnsasu 2021-06-01 01:16:45 +08:00 2
coroutine 是一种无须借助操作系统提供的线程 /进程设施即可实现多任务的机制。
假设当前有两个 task,执行完全一样的代码 while(1) {print"1"} 显然由于没有线程,初始执行的那个 task 会一直执行下去,另一个 task 永远没机会执行。 但如果引入一个调度器和 [打断 /恢复] 的机制,就能够实现 task 间的切换,此时 task 代码类似这样 while(1) {print"1";yield} yield 语句处将执行流跳到这个 task 外,比如调度器;这时候调度器就能将执行流转给另一个 task,另一个 task 从之前 yield 处恢复执行。 两个 task 不断执行 yield,不断交换执行权,就能让两个 task 的循环都可以同时进行下去,实现并发 协程需要主动让出执行权,而操作系统的线程借助时间中断可以在当前 task 的任何地方打断并切换,这是协程最典型的特征。不过一般出于写法一致性等理由,会把协程的主动交换点藏在一些不容易发现的地方,比如 await 、yield from 、coroutine.sleep 等,这些语句 /函数其实都是把执行权交到另一个协程( await )或调度器( sleep )上。 任意一个协程把执行权交给调度器后调度器发现某个协程的 sleep 已超时,它把执行权交回 sleep 的这个协程,从这个协程来看就会好像自己真的 sleep 了一样。执行权交给目标协程后目标协程完全结束并返回,把执行权交给上层 wait 中的协程(完全结束前只可能把执行权交给调度器或第三个协程),从 wait 协程来看就好像自己真的等到目标协程返回才继续一样。 stackful/stackless 只是实现 [打断 /恢复] 那个恢复机制的做法不同而已 |
11
Rwing 2021-06-01 08:31:58 +08:00
c# 的 async/await 和 js 的 async/await 应该不是一回事吧
|
12
bytesfold 2021-06-01 09:08:06 +08:00
建议读 《深入了解计算机系统》
|
13
wanguorui123 2021-06-01 09:35:22 +08:00
协程就是多线程的 NodeJS 事件队列
|
14
Mogamigawa 2021-07-20 14:50:09 +08:00 via iPhone
接受协程的角色设定就行了,大脑简单点不要太复杂。
|