Max*_*kyi 6 javascript google-chrome v8 node.js
很长一段时间,我认为Chrome 和 Node.js 中使用的事件循环实现(libuv?)使用线程。但后来我正在阅读这篇关于 Java 轻量级线程的文章,其中说明了以下内容:
...不是为每个并发任务(和阻塞任务)创建线程,而是一个专用线程(称为事件循环)查看分配给非反应模型中线程的所有任务,并在相同的 CPU 内核。
还有这本书《计算机系统》。并发应用程序一章中的程序员视角指出,现代操作系统提供了三种构建并发程序的基本方法(实现逻辑流的 3 种方法):
流程。通过这种方法,每个逻辑控制流都是一个由内核调度和维护的进程。由于进程具有独立的虚拟地址空间,想要相互通信的流必须使用某种显式进程间通信 (IPC) 机制。
I/O 多路复用。这是一种并发编程形式,其中应用程序在单个进程的上下文中显式调度它们自己的逻辑流。逻辑流被建模为状态机,作为数据到达文件描述符的结果,主程序显式地从一个状态转换到另一个状态。由于程序是单个进程,所有流共享相同的地址空间。
线程。线程是在单个进程的上下文中运行并由内核调度的逻辑流。您可以将线程视为其他两种方法的混合体,像进程流一样由内核调度,并像 I/O 多路复用流一样共享相同的虚拟地址空间。
所以现在我想知道事件循环是否属于I/O multiplexing
逻辑流并且不使用线程?
我与 V8 团队无关,但我会尽力回答这个问题。
首先,V8 本身与事件循环无关。Node.js 使用 libuv 来实现事件循环以及特定于操作系统的 API(网络、FS 等)的抽象。事件循环本身在单个操作系统线程上运行,并且大多数网络操作在基于该线程的 I/O 多路复用 API(epoll、kqueue 等)上执行。
但libuv还有一个线程池来运行阻塞I/O(例如FS、DNS查找)和CPU密集型操作(例如加密)。线程池通过内存队列与事件循环集成(通信)。当必须启动阻塞/CPU 密集型任务时,它会被放入队列中,稍后其中一个线程开始处理它。
因此,Node.js 使用多种方法来实现用户操作之间的并发:操作系统线程(顺便说一句,这包括worker_threads
模块)、I/O 多路复用、多进程(与child_process
模块)。
V8 还使用许多操作系统线程来实现自己的目的(例如 GC),但它不需要了解事件循环或为操作系统级 API 提供任何抽象。它的目标是执行给定的 JS 代码并提供可靠的嵌入器 API,以便您可以用它构建浏览器/运行时。
归档时间: |
|
查看次数: |
218 次 |
最近记录: |