此问题已在此处有答案:
How do JavaScript closures work?(86回答)
How are Go closures layed out in memory?(2个答案)
昨天关门了。
这篇文章是昨天编辑并提交审查的。
当我们启动OS级别的线程时,我们将为每个线程创建一个堆栈,这有一些成本。在此讨论:Threads vs. Async使用协程,异步和await可以降低此成本。
那么,程序如何在异步函数中存储局部变量,以便当我们回到函数时,我们可以恢复所有变量,而无需使用另一个堆栈?这是如何实施的?
也许我应该问一个更具体的问题,这在Golang/javascript中是如何工作的?这些是协同程序被认为是高效的地方。它们可能使用多线程,但并不是所有的协程都是线程。
1条答案
按热度按时间57hvy0tb1#
我无法回答Go方面的问题,因为我自己并不真正涉足那里,但JavaScript方面希望更容易一些,你可以从那里得到类似的东西。
在JavaScript中(取决于实现),您被严格限制为一个线程,这意味着单个堆栈。由于所有线程共享堆空间,并且大多数JS实现堆分配几乎所有内容,并且只在堆栈上保留引用,因此所有线程都可以同时访问数据,无论从何处访问它们。
异步函数实际上与此关系很小。具体来说,异步函数只是通知引擎 * 稍后返回此 * 的常规函数。它们也访问相同的变量。
这就是垃圾收集的用武之地。GC允许源代码定义变量,并对其进行引用计数。当你调用一个异步函数时,变量被声明,这意味着它们的引用计数为0。重要的是要注意,变量是在调用函数时声明的,而不是在调用程序时声明的,这意味着函数的每次调用都会重新分配其内存-为每次调用保留一个新的堆分配值。这基本上是一种封闭。所有函数在创建堆栈框架时都定义了闭包,闭包中使用的所有变量都有一些定义好的方法来访问它们的值。
引用计数机制确保只要需要就可以访问这些数据,并且可以确保尽管变量名相同,但实际上引用的是不同的内存。
总而言之,异步函数在管理内存方面没有任何魔力,它们只是保持自己的状态。原则上,这与调用同步函数完全相同,只是它是无序运行的。
我认为Go做了非常相似的事情。在异步函数的多线程方面,取决于你是否使用堆分配的值,同样的原则适用,除非你显式共享内存,Go建议不要这样做。