• 技术文章 >web前端 >js教程

    聊聊Node.js中的进程、线程、协程与并发模型

    青灯夜游青灯夜游2022-07-19 20:11:07转载237

    Node.js 现在已成为构建高并发网络应用服务工具箱中的一员,何以 Node.js 会成为大众的宠儿?本文将从进程、线程、协程、I/O 模型这些基本概念说起,为大家全面介绍关于 Node.js 与并发模型的这些事。

    进程

    我们一般将某个程序正在运行的实例称之为进程,它是操作系统进行资源分配和调度的一个基本单元,一般包含以下几个部分:

    进程具有以下特征:

    需要注意的是,如果一个程序运行了两遍,即便操作系统能够使它们共享代码(即只有一份代码副本在内存中),也不能改变正在运行的程序的两个实例是两个不同的进程的事实。

    在进程的执行过程中,由于中断、CPU 调度等各种原因,进程会在下面几个状态中切换:

    1.png

    通过上面的进程状态切换图可知,进程可以从运行态切换成就绪态和阻塞态,但只有就绪态才能直接切换成运行态,这是因为:

    线程

    有些时候,我们需要使用线程来解决以下问题:

    关于线程,我们需要知道以下几点:

    了解了线程的基本特征,下面我们来聊一下常见的几种线程类型。

    内核态线程

    内核态线程是直接由操作系统支持的线程,其主要特点如下:

    用户态线程

    用户态线程是完全建立在用户空间的线程,其主要特点如下:

    轻量级进程(LWP)

    轻量级进程(LWP)是建立在内核之上并由内核支持的用户线程,其主要特点如下:

    小结

    上文我们对常见的线程类型(内核态线程、用户态线程、轻量级进程)进行了简单介绍,它们各自有各自的适用范围,在实际的使用中可根据自己的需要自由地对其进行组合使用,比如常见的一对一、多对一、多对多等模型,由于篇幅限制,本文对此不做过多介绍,感兴趣的同学可自行研究。

    协程

    协程(Coroutine),也叫纤程(Fiber),是一种建立在线程之上,由开发者自行管理执行调度、状态维护等行为的一种程序运行机制,其特点主要有:

    在 JavaScript 中,我们经常用到的 async/await 便是协程的一种实现,比如下面的例子:

    function updateUserName(id, name) {
      const user = getUserById(id);
      user.updateName(name);
      return true;
    }
    
    async function updateUserNameAsync(id, name) {
      const user = await getUserById(id);
      await user.updateName(name);
      return true;
    }

    上例中,函数 updateUserNameupdateUserNameAsync 内的逻辑执行顺序是:

    两者的主要区别在于其实际运行过程中的状态控制:

    通过上面的分析我们可以大胆猜测:协程要解决的并非是进程、线程要解决的程序并发问题,而是要解决处理异步任务时所遇到的问题(比如文件操作、网络请求等);在 async/await 之前,我们只能通过回调函数来处理异步任务,这很容易使我们陷入回调地狱,生产出一坨坨屎一般难以维护的代码,通过协程,我们便可以实现异步代码同步化的目的。

    需要牢记的是:协程的核心能力是能够将某段程序挂起并维护程序挂起位置的状态,并在未来某个时刻在挂起的位置恢复,并继续执行挂起位置后的下一段程序。

    I/O 模型

    一个完整的 I/O 操作需要经历以下阶段:

    我们可将 I/O 操作大致分为阻塞 I/O非阻塞 I/O同步 I/O异步 I/O 四种类型,在讨论这些类型之前,我们先熟悉下以下两组概念(此处假设服务 A 调用了服务 B):

    很多人经常将阻塞/非阻塞同步/异步搞混淆,故需要特别注意:

    了解了阻塞/非阻塞同步/异步,我们来看具体的 I/O 模型

    阻塞 I/O

    定义:用户进(线)程发起 I/O 系统调用后,用户进(线)程会被立即阻塞,直到整个 I/O 操作处理完毕并将结果返回给用户进(线)程后,用户进(线)程才能解除阻塞状态,继续执行后续操作。

    特点:

    非阻塞 I/O

    定义:

    特点:

    同(异)步 I/O

    用户进(线)程发起 I/O 系统调用后,如果该 I/O 调用会导致用户进(线)程阻塞,那么该 I/O 调用便为同步 I/O,否则为 异步 I/O

    判断 I/O 操作同步异步的标准是用户进(线)程与 I/O 操作的通信机制,其中:

    Node.js 的并发模型

    Node.js 采用的是单线程、基于事件驱动的异步 I/O 模型,个人认为之所以选择该模型的原因在于:

    总之,本着简单、高效的目的,Node.js 采用了单线程、基于事件驱动的异步 I/O 模型,并通过主线程的 EventLoop 和辅助的 Worker 线程来实现其模型:

    需要注意的是,Node.js 并不适合执行 CPU 密集型(即需要大量计算)任务;这是因为 EventLoop 与 JavaScript 代码(非异步事件任务代码)运行在同一线程(即主线程),它们中任何一个如果运行时间过长,都可能导致主线程阻塞,如果应用程序中包含大量需要长时间执行的任务,将会降低服务器的吞吐量,甚至可能导致服务器无法响应。

    总结

    Node.js 是前端开发人员现在乃至未来不得不面对的技术,然而大多数前端开发人员对 Node.js 的认知仅停留在表面,为了让大家更好地理解 Node.js 的并发模型,本文先介绍了进程、线程、协程,接着介绍了不同的 I/O 模型,最后对 Node.js 的并发模型进行了简单介绍。虽然介绍 Node.js 并发模型的篇幅不多,但笔者相信万变不离其宗,掌握了相关基础,再深入理解 Node.js 的设计与实现必将事半功倍。

    最后,本文若有纰漏之处,还望大家能够指正,祝大家快乐编码每一天。

    更多node相关知识,请访问:nodejs 教程

    以上就是聊聊Node.js中的进程、线程、协程与并发模型的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    上一篇:JavaScript知识点总结之DOM 下一篇:20个JS技巧,助你提升工作效率,再也不做加班人!
    VIP课程(WEB全栈开发)

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• 聊聊node+multiparty怎么实现文件上传• 如何安装并管理多版本node?方法介绍• 聊聊怎么使用Node.js创建一个简单的HTTP服务器• 详解如何使用Node.js开发一个简单图片爬取功能• 推荐11个受欢迎的Node.js 框架,快放入收藏夹吧!• 进程和线程如何理解?Node.js中的进程和线程是怎样的?• 火了!新的JavaScript运行时:Bun,性能完爆Node
    1/1

    PHP中文网