首页
注册
登录
lxdlam 最近的时间轴更新
ONLINE
lxdlam
Stay hungry, stay foolish
V2EX 第 91515 号会员,加入于 2015-01-13 12:44:59 +08:00
今日活跃度排名
17334
blog.lxdlam.com
北京海淀
lxdlam
lxdlam
lxdlam
lxdlam
提问
技术话题
好玩
工作信息
交易信息
城市相关
根据 lxdlam 的设置,主题列表被隐藏
二手交易
相关的信息,包括已关闭的交易,不会被隐藏
lxdlam 最近回复了
44 天前
回复了
HikariLan
创建的主题
›
Linux
›
从进程到协程:计算机的并发编程之路
async/await 真正的含义并不是“显式切换上下文”,如此说来为何 goroutine 也需要 "go func()" 才能启动并发调度?这难道不是一种类似于 "yield something" 的显式切换上下文吗?
从 Delimited Continuation 的角度说,async/await 是 F#/C# 发明出来用来模仿 Delimited Continuation 的 shift/reset, prompt/control 算子的,这一定程度上解释了函数染色问题从何而来:我们需要显式标记哪些部分能够被编译期改写,这样才能准确地把 k : Continuation 传到这些部分。与之相对的是 Scheme 的 continuation ,任何 continuation 都是无界的,也就是说会捕获到整个 runtime ,这对一个**后续接入** continuation 的语言实现有巨大的 breaking change (在 chez 中执行 `(call/cc (lambda (cc) (cc cc)))`,你会得到 `#<system continuation in new-cafe>`)。
而这样说有一些吊书袋,我们不妨简单思考一下所谓的 coroutine 是怎么编译的?
当我们遇到一个类似于如下的代码
```
let coro = async { time.sleep(5000) }
// some busywork
await coro
```
时,我们单纯从语法考虑,我们如何将 coro 正确编译成我们想要的结构呢?我们自然能想到很多种做法,至少我们可以为 coro 创建一个简单的 reference object ,去轮询来看它是否完成,并把 await 自动重写成 while not coro.ref.isFinished() {} 的一个 busyloop 就可以了(对于有栈来说可以是用户态的 uthread.join(),对于无栈来说可以是 state in [Done, Exception])。
所以,本质来说,async/await 是定界,界定了到底哪些代码需要被识别成一个 remote track 的对象,并正确插入调度代码。
这个的后续遗留了更多好玩的问题,感兴趣的朋友可以从这些起点思考:
1. 根据前文描述,"go func()" 某种程度也是定界,那跟 async/await 的核心区别是什么?这将为你导向有栈和无栈最核心的区别,究竟“栈”如何让 goroutine 不需要考虑函数染色问题?
2. 如何实现一个可用级别的编译器,编译我们的协程?他们的底层模型其实很相似,但是要搞懂无栈协程的编译难度比较大,你可能需要真的理解 continuation 和 cps conversion 才能明白看似简单的东西背后有多少篇 paper 和大佬支撑。
»
lxdlam 创建的更多回复
关于
·
帮助文档
·
博客
·
API
·
FAQ
·
实用小工具
·
4649 人在线
最高记录 6679
·
Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 11ms ·
UTC 04:01
·
PVG 12:01
·
LAX 21:01
·
JFK 00:01
Developed with
CodeLauncher
♥ Do have faith in what you're doing.