如何可视化正在执行协同例程功能的单个线程的调用堆栈?
是否有任何语言实现支持在不同线程中运行的协同例程?
我遇到了令人敬畏的Stack Overflow问题Difference between a “coroutine” and a “thread”?。在这个问题中,我看到了这一点:
[I]如果你有一个例程做一些工作,它执行一个你知道会阻塞一段时间的操作(即一个网络请求),通过一个协同例程你可以立即切换到另一个例程而不需要包含系统调度程序的开销在这个决定中 - 是的,程序员必须指定协同例程何时可以切换。
在JS中,如果我有一个例程(某个函数)是一个CPU绑定操作(不是IO /网络请求),那么我还可以使用协同例程(即JS中的生成器)吗?或者我应该使用Web Workers所以我不阻止事件循环(即至少UI渲染发生)?
我们来看一个简单的生成器示例:
const doubleGen = function*(initValue) {
const value = yield initValue * 2;
return value * 2;
};
const gen = doubleGen(2);
console.log("pre");
console.log(gen.next());
console.log("middle");
console.log(gen.next(4));
console.log("post");
我们可以将其重写为:
const doubleGen = (initValue) => {
const yieldStatements = [ // the function body statements
() => initValue * 2,
(inputValue) => {
const value = inputValue;
return value * 2;
}
];
return {
next(inputValue) {
return {
value: yieldStatements.shift()(inputValue),
done: !yieldStatements.length
}
}
}
};
const gen = doubleGen(2);
console.log("pre");
console.log(gen.next());
console.log("middle");
console.log(gen.next(4));
console.log("post");
因此,您可以看到生成器实际工作方式没有神奇之处,因为它们只是使用迭代器模式来一个接一个地控制连续调用。
你甚至可以将它简单地愚蠢到一个接一个的简单函数调用,所以它默认都是同步的。
如果计算量很大,您确实可以将它们卸载到基本上是独立线程的Web工作者,并释放主线程一段时间,直到这些工作者的最终有效负载到达。
所以我想说的是,调用堆栈看起来像是以普通的同步方式执行任何其他正常函数的调用堆栈。没有特殊处理只是因为有*
标志或yield
关键字。
希望它澄清一下。