Nodejs中的事件循环使用什么逻辑流模型(Google Chrome)

What logical flow model is used for event loop in Nodejs (Google Chrome)

很长一段时间我都认为事件循环实现(libuv?) used in Chrome and Node.js used threads. But then I was reading this article 在 Java 中的轻量级线程上声明如下:

...instead of creating threads for each concurrent task (and blocking tasks), a dedicated thread (called an event loop) looks through all the tasks that are assigned to threads in a non-reactive model, and processes each of them on the same CPU core.

本书 Computer Systems. A Programmer’s Perspective 在关于并发应用程序的章节中指出,现代操作系统提供了三种基本的构建方法 并发程序(实现逻辑流的 3 种方法):

  • Processes. With this approach, each logical control flow is a process that is scheduled and maintained by the kernel. Since processes have separate virtual address spaces, flows that want to communicate with each other must use some kind of explicit interprocess communication (IPC) mechanism.

  • I/O multiplexing. This is a form of concurrent programming where applications explicitly schedule their own logical flows in the context of a single process. Logical flows are modeled as state machines that the main program explicitly transitions from state to state as a result of data arriving on file descriptors. Since the program is a single process, all flows share the same address space.

  • Threads. Threads are logical flows that run in the context of a single process and are scheduled by the kernel. You can think of threads as a hybrid of the other two approaches, scheduled by the kernel like process flows and sharing the same virtual address space like I/O multiplexing flows.

所以现在我想知道事件循环是否属于 I/O multiplexing 逻辑流程并且不使用线程?

我与V8团队无关,但我会尽力回答这个问题

首先,V8本身与事件循环无关。 Node.js 使用 libuv 来实现事件循环以及对 OS-特定 APIs(网络、FS 等)的抽象。事件循环本身是 运行 在单个 OS 线程上,并且大多数网络操作都是在该线程上基于 I/O 多路复用 APIs(epoll、kqueue 等)执行的。 ).

但是 libuv 也有一个线程池来 运行 阻塞 I/O(例如 FS、DNS 查找)和 CPU 密集型操作(例如加密)。线程池通过内存队列与事件循环集成(通信)。当必须启动 blocking/CPU 密集型任务时,它会被放入队列,稍后其中一个线程开始处理它。

因此,Node.js 使用多种方法在用户操作之间实现并发:OS 线程(顺便说一句,这包括 worker_threads 模块),I/O 多路复用,多个进程(使用 child_process 模块)。

V8 还使用多个 OS 线程来实现自己的目的(比如 GC),但它不需要知道事件循环或为 OS级APIs。它的目标是,嗯,执行给定的 JS 代码并提供一个可靠的嵌入器 API,这样你就可以用它构建一个 browser/runtime。