如何可视化正在执行协同例程函数的单个线程的调用堆栈?
是否有任何语言实现支持在不同线程中运行的协同例程?
我遇到了令人敬畏的Stack Overflow问题Difference between a “coroutine” and a “thread”?。在这个问题中,我看到了这一点:
[我]你有一个例程做一些工作,它执行一个你知道会阻塞一段时间的操作(即一个网络请求),通过一个协同例程,你可以立即切换到另一个例程而不需要包括在内这个决定中的系统调度程序 - 是的,程序员必须指定协同例程何时可以切换。
在JS中,如果我有一个例程(某个函数)是一个CPU绑定操作(不是IO /网络请求),那么我还可以使用协同例程(即JS中的生成器)吗?或者我应该使用Web Workers所以我不阻止事件循环(即至少UI渲染发生)?
答案 0 :(得分:1)
让我们看一个简单的生成器示例:
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-worker,并释放你的主线程一段时间,直到这些工作人员的最终有效负载到达。
所以我想说的是调用堆栈看起来像是以普通的同步方式执行任何其他正常函数的调用堆栈。没有特殊处理只是因为有*
符号或yield
关键字。
希望它澄清。