我正在查看node.js
的详细信息并了解到,它支持异步编程,但实质上它提供了单线程模型。
在这种情况下如何处理异步编程?是否像运行时本身创建和管理线程,但程序员无法显式创建线程?如果有人可以指点我一些资源来了解这一点,那就太好了。
答案 0 :(得分: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中你无法对线程做任何事情。
答案 1 :(得分:10)
Ryan说得最好:sync / async与单/多线程正交。对于单线程和多线程情况,有一个主事件循环使用Reactor Pattern调用已注册的回调。对于单线程情况,在主线程上顺序调用回调。对于多线程情况,它们在不同的线程上调用(通常使用线程池)。这实际上是一个争论的问题:如果所有请求都需要同步访问单个数据结构(比如订阅者列表),那么拥有多个线程的好处可能会减少。这是依赖于问题的。
就实现而言,如果框架是单线程的,那么很可能使用poll/select系统调用,即OS正在触发异步事件。
答案 2 :(得分:1)
要重述服务生/厨师的比喻:
您的程序是一个服务员(“ you”),而JavaScript运行时是一个厨房,厨房里到处都是厨师,可以做您要的事情。
服务员和厨房之间的接口由队列来协调,因此在容量过大的情况下请求不会丢失。
因此,您的程序被分配了一个执行线程。您一次只能等待一张桌子。每次您要卸载一些工作时(例如制作食物/发出网络请求),您都要跑到厨房并将订单钉在板子(队列)上,以供厨师(运行时)在有空余时取用。当订单准备好时,厨师会通知您(他们会给您回电)。同时,您要等待另一张桌子(您没有被厨房挡住)。
因此,已接受的答案具有误导性。 JavaScript运行时在定义上是多线程的,因为I / O不会阻止您的JavaScript程序。作为服务生,您可以在厨房做饭的同时继续为客户提供服务。这涉及至少两个执行线程。现实情况是,运行时将在后台维护多个执行线程,以便有效地直接服务与您的脚本相对应的单个线程。
根据设计,只有一个执行线程分配给JavaScript程序的同步运行。这是一件好事,因为它使您的程序更容易推理,而不必自己处理多个执行线程。不用担心:尽管如此,您的JavaScript程序仍然会变得非常复杂!