【问题标题】:How does concurrency work in nodejs?并发如何在 nodejs 中工作?
【发布时间】:2015-07-10 16:55:58
【问题描述】:

我试图了解并发在像 nodejs 这样的单线程环境中是如何工作的。

假设我有这个代码:

var fs = require('fs');

fs.readFile('file1', function one(err, data) {
  // some code...
});

fs.readFile('/file2', function two(err, data) {
  // some code...
});

现在每个fs.readFile 调用都是异步的。因此,它们同时运行。但是如果这一切都发生在一个线程中,那么并发是如何实现的呢? function onefunction two 是在同一线程上运行还是在不同线程上运行?

基本上,node.js 是如何处理并发的?

【问题讨论】:

标签: node.js multithreading concurrency


【解决方案1】:

就Node而言,只有一个线程。异步调用被放入事件队列中,并且只在下一个滴答声中运行。

对于 Node 传递给 C++ 的代码,所有的赌注都没有了。那里可能有也可能没有线程。但这并不会真正影响到你。

对我来说最有效的解释是"What the heck is the event loop anyway?" by Philip Roberts,因为他展示的慢动作可视化工具让一切都非常清楚(无论如何对我来说)。

您可以在线试用 Philip 的工具 Loupe

【讨论】:

  • 这是一个不错的视频!
  • 菲利普罗伯茨视频+1。这是我见过的 JS 调用堆栈/事件循环协作的最佳可视化之一。
【解决方案2】:

node.js 的特点是 所有东西都是同时运行的,除了你的代码

所以,这意味着实际上有很多线程在 node.js 虚拟机(或线程池,如果您愿意)中运行,并且每当您调用异步函数(如执行 i/o 操作)时都会使用这些线程关于文件、访问数据库、请求 url 等。

但是,对于您的代码,只有一个线程,它处理来自event queue 的事件。因此,当您注册一个回调时,它的引用实际上会传递给后台工作线程,并且一旦异步操作完成,新事件就会使用该回调添加到事件队列中。

【讨论】:

  • 那么,基本上,在我提供的代码中,file1 和 file2 是在不同的线程上读取的?
  • 虽然可能会为同一个工作线程分配两个任务,但应该认为这不太可能。但读取这些文件的绝对是工作线程,而不是您的事件循环线程。
【解决方案3】:

Node.js 确实使用多个线程来处理 io 用户的封面,但这对用户是隐藏的。应用程序环境(即您的代码)只能访问单个线程,但 Node.js 透明地将 io 移交给单独的线程,用户无需处理它。

在您的情况下,函数一和函数二都在同一个线程中运行,但读取文件数据的实际 io 操作是在不同的线程中执行的。

可以在here 找到关于 Node.js 的线程/io 模型的更详细描述,并且可以在here 阅读一组不错的类似示例。

【讨论】:

    猜你喜欢
    • 2014-01-18
    • 2014-06-18
    • 2019-02-14
    • 1970-01-01
    • 2022-01-23
    • 2016-11-12
    • 1970-01-01
    • 2018-12-28
    • 2021-12-29
    相关资源
    最近更新 更多