异步编程如何在单线程编程模型中工作?

Rak*_*h K 62 asynchronous node.js

我正在仔细研究node.js并了解它,它支持异步编程,但实际上它提供了单线程模型.

在这种情况下如何处理异步编程?是否像运行时本身创建和管理线程,但程序员无法显式创建线程?如果有人可以指点我一些资源来了解这一点,那就太好了.

Rya*_*cox 79

现在跟我说吧:异步编程并不一定意味着多线程.

Javascript是一个单线程运行时 - 你根本无法在JS中创建新线程,因为语言/运行时不支持它.

弗兰克说它是正确的(尽管是迟钝的)在英语中:有一个主事件循环可以处理事情进入你的应用程序.因此,"处理此HTTP请求"将被添加到事件队列中,然后在适当时由事件循环处理.

当您调用异步操作(例如,mysql数据库查询)时,node.js会向mysql发送"嘿,执行此查询".由于此查询需要一定的时间(毫秒),node.js的执行使用MySQL异步库查询-找回事件循环,做点别的有等待的mysql要回美国.就像处理那个HTTP请求一样.

编辑:相比之下,node.js 可以简单地等待(无所事事)让mysql回到它.这称为同步调用.想象一下一家餐馆,你的服务员把你的订单提交给厨师,然后坐下来,在厨师做饭的时候揉捏他/她的拇指.在餐馆中,就像在node.js程序中一样,这种行为是愚蠢的 - 你有其他顾客,他们很饿,需要服务.因此,您希望尽可能保持异步,以确保一个服务员(或node.js进程)为尽可能多的人服务.

编辑完成

Node.js使用C库与mysql进行通信,因此从技术上讲,这些C库可以产生线程,但在Javascript中你不能对线程做任何事情.

  • 更精确地."Node.js通过异步API与mysql通信.异步API的实现在C中,实现可能只是通过线程池运行同步API".异步API可能在内部使用线程池的事实是您不关心的低级细节. (9认同)
  • 我认为最好避免使用"线程"这个词 - 当人们听到它时会跳到错误的结论.异步调用可以使用线程,或者分叉进程,或者做任何事情; 重要的是,事件循环中可能会发生回调或事件. (3认同)
  • 餐厅 - 服务员 - 厨师的例子真的很好,+1. (3认同)

Fra*_*ank 11

Ryan说得最好:sync/async与单/多线程正交.对于单线程和多线程情况,有一个主事件循环使用Reactor模式调用已注册的回调.对于单线程情况,在主线程上顺序调用回调.对于多线程情况,它们在不同的线程上调用(通常使用线程池).这实际上是一个争论的问题:如果所有请求都需要同步访问单个数据结构(比如订阅者列表),那么拥有多个线程的好处可能会减少.这是依赖于问题的.

就实现而言,如果框架是单线程的,则可能使用轮询/选择系统调用,即OS正在触发异步事件.


Ben*_*Ben 5

重申一下服务员/厨师的类比:

你的程序是一个服务员(“你”),而 JavaScript 运行时是一个厨房,里面都是厨师,按照你的要求做事。

服务员和厨房之间的接口是通过队列来协调的,因此在产能过剩的情况下请求不会丢失。

所以你的程序被分配了一个执行线程。您一次只能等一张桌子。每次您想要卸载一些工作(例如制作食物/发出网络请求)时,您都会跑到厨房并将订单固定到面板(队列)上,以便厨师(运行时)在有闲置能力时接货。当订单准备好时,厨师会通知您(他们会给您回电)。与此同时,你去等另一张桌子(你不会被厨房挡住)。

所以接受的答案是有误导性的。JavaScript 运行时本质上是多线程的,因为 I/O 不会阻塞您的 JavaScript 程序。作为服务员,您可以在厨房做饭的同时继续为顾客服务。这至少涉及两个执行线程。现实情况是,运行时将在幕后维护多个执行线程,以便有效地服务于直接对应于脚本的单个线程。

根据设计,只有一个执行线程被分配给 JavaScript 程序的同步运行。这是一件好事,因为它使您的程序比必须自己处理多个执行线程更容易推理。别担心:您的 JavaScript 程序仍然会变得非常复杂!