Maison  >  Article  >  interface Web  >  Parlons des processus, des threads, des coroutines et des modèles de concurrence dans Node.js

Parlons des processus, des threads, des coroutines et des modèles de concurrence dans Node.js

青灯夜游
青灯夜游avant
2022-07-19 20:11:072519parcourir

Parlons des processus, des threads, des coroutines et des modèles de concurrence dans Node.js

Node.js est désormais devenu membre de la boîte à outils permettant de créer des services d'applications réseau à haute concurrence. Pourquoi Node.js est-il devenu le chouchou du public ? Cet article commencera par les concepts de base des processus, des threads, des coroutines et des modèles d'E/S, et vous donnera une introduction complète à Node.js et au modèle de concurrence.

Processus

Nous appelons généralement l'instance en cours d'exécution d'un programme un processus. Il s'agit d'une unité de base pour l'allocation et la planification des ressources par le système d'exploitation. Elle comprend généralement les parties suivantes :

  • Programme : c'est-à-dire le. le code à exécuter est utilisé pour décrire la fonction à remplir par le processus ;
  • Zone de données : l'espace de données traité par le processus, y compris les données, la mémoire allouée dynamiquement, la pile utilisateur de fonctions de traitement, les programmes modifiables et d'autres informations ;
  • Élément de la table de processus : afin de mettre en œuvre le modèle de processus, le système d'exploitation maintient une table appelée
  • ), qui contient des informations importantes sur l'état du processus telles que le compteur de programme, le pointeur de pile, l'allocation de mémoire, l'état des fichiers ouverts, les informations de planification, etc. , garantissant ainsi qu'après la suspension d'un processus, le système d'exploitation peut relancer correctement le processus. 进程表的表格,每个进程占用一个进程表项(也叫进程控制块
Les processus ont les caractéristiques suivantes :

    Dynamique : l'essence d'un processus est un processus d'exécution d'un programme dans un système multi-programmation. Les processus sont générés et meurent dynamiquement.
  • Concurrence : tout processus peut interagir avec. autres processus Les processus s'exécutent simultanément ;
  • Indépendance : un processus est une unité de base qui peut s'exécuter indépendamment, et c'est également une unité indépendante pour l'allocation et la planification du système
  • Asynchronicité : en raison de contraintes mutuelles entre les processus, les processus ont une exécution intermittente ; , c'est-à-dire que les processus avancent à des vitesses indépendantes et imprévisibles.
Il convient de noter que si un programme est exécuté deux fois, même si le système d'exploitation peut lui permettre de partager du code (c'est-à-dire qu'une seule copie du code est en mémoire), cela ne peut pas changer que les deux instances du programme en cours d'exécution sont deux Le fait de processus différents.

Pendant l'exécution du processus, pour diverses raisons telles que les interruptions et la planification du CPU, le processus basculera entre les états suivants :

Parlons des processus, des threads, des coroutines et des modèles de concurrence dans Node.js

    État d'exécution : le processus est en cours d'exécution en ce moment et occupe le CPU ;
  • État prêt : le processus est prêt à ce moment et peut s'exécuter à tout moment, mais il est temporairement arrêté car d'autres processus sont en cours d'exécution.
  • État bloqué : le processus est dans un état bloqué à ce moment, sauf événement externe ; (par exemple, les données de saisie au clavier sont arrivées), sinon le processus ne s'exécutera pas.
Comme le montre le diagramme de commutation d'état du processus ci-dessus, le processus peut passer de l'état d'exécution à l'état prêt et à l'état bloqué, mais seul l'état prêt peut être directement commuté à l'état d'exécution.

    passe de l'état d'exécution à l'état prêt Cela est dû au planificateur de processus, car le système estime que le processus actuel a pris trop de temps CPU et décide de laisser d'autres processus utiliser le temps CPU et le planificateur de processus ; fait partie du système d'exploitation, et le processus ne ressent même pas l'existence du planificateur
  • Le passage de l'état d'exécution à l'état de blocage est dû aux propres raisons du processus (comme l'attente de la saisie au clavier de l'utilisateur) ; le processus ne peut pas continuer à s'exécuter et ne peut que se suspendre et attendre qu'un certain événement (tel que l'arrivée des données saisies par le clavier) se produise lorsque l'événement correspondant se produit, le processus passe d'abord à l'état prêt si aucun autre. Si le processus est en cours d'exécution à ce moment-là, il passe immédiatement à l'état d'exécution. Sinon, le processus restera à l'état prêt et attendra la planification par le planificateur de processus.

Threads

Parfois, nous devons utiliser des threads pour résoudre les problèmes suivants :

    À mesure que le nombre de processus augmente, le coût de commutation entre les processus deviendra de plus en plus important, et l'utilisation efficace du processeur augmentera également de plus en plus bas, ce qui peut provoquer le gel du système dans les cas graves
  • Chaque processus a son propre espace mémoire indépendant, et les espaces mémoire entre les processus sont isolés les uns des autres, et certaines tâches peuvent devoir être partagées ; certaines données, la synchronisation des données entre plusieurs processus est trop lourde.
À propos des threads, nous devons connaître les points suivants :

    Un thread est un flux de contrôle séquentiel unique dans l'exécution d'un programme. C'est la plus petite unité que le système d'exploitation peut effectuer pour planifier les opérations. est le cœur du processus. Unité d'exécution réelle ;
  • Un processus peut contenir plusieurs threads, chaque thread effectue différentes tâches en parallèle ;
  • Tous les threads d'un processus partagent l'espace mémoire du processus (y compris le code, les données, le tas, etc. ) et certaines informations sur les ressources (telles que les fichiers ouverts et les signaux système) ;
  • Les threads d'un processus ne sont pas visibles dans les autres processus ;
Maintenant que nous comprenons les caractéristiques de base des fils, parlons de plusieurs types de fils courants.

Fils d'état du noyau

Les threads d'état du noyau sont des threads directement pris en charge par le système d'exploitation. Ses principales fonctionnalités sont les suivantes :

  • La création, la planification, la synchronisation et la destruction des threads sont effectuées par le noyau du système, mais sa surcharge est relativement coûteuse.
  • Le noyau peut mapper les threads de l'état du noyau à chaque processeur, ce qui permet à un cœur de processeur de correspondre facilement. à un seul thread du noyau, rivalisant ainsi pleinement pour et utilisant les ressources du processeur ;
  • Accès uniquement au code et aux données du noyau 
  • L'efficacité de la synchronisation des ressources et du partage des données est inférieure à celle du processus.

Thread en mode utilisateur

Le thread en mode utilisateur est un thread entièrement construit dans l'espace utilisateur. Ses principales fonctionnalités sont les suivantes :

  • La création, la planification, la synchronisation et la destruction des threads sont complétées par l'espace utilisateur, et sa surcharge est très faible ;
  • Étant donné que les threads en mode utilisateur sont maintenus par l'espace utilisateur, le noyau ne perçoit pas du tout l'existence des threads en mode utilisateur. Par conséquent, le noyau planifie et alloue uniquement des ressources aux processus auxquels ils sont affectés. appartiennent, et la planification et l'allocation des ressources des threads dans le processus sont gérées par le programme lui-même. Il est très probable que si un thread en mode utilisateur est bloqué lors d'un appel système, l'ensemble du processus sera bloqué
  • Peut ; pour accéder à tous les espaces d'adressage partagés et aux ressources système du processus auquel il appartient ;
  • La synchronisation des ressources et le partage des données sont plus efficaces.

Lightweight Process (LWP)

Lightweight Process (LWP) est un thread utilisateur construit au-dessus du noyau et pris en charge par le noyau. Ses principales fonctionnalités sont les suivantes :

  • L'espace utilisateur ne peut s'exécuter que via. léger Les processus légers (LWP) utilisent des threads du noyau, qui peuvent être considérés comme un pont entre les threads du mode utilisateur et les threads du noyau. Par conséquent, ce n'est qu'en prenant en charge les threads du noyau que nous pouvons avoir des processus légers (LWP) ; le fonctionnement du processus de niveau (LWP) nécessite l'espace du mode utilisateur pour lancer un appel système. Le coût de cet appel système est relativement élevé (nécessitant de basculer entre le mode utilisateur et le mode noyau)

  • Chaque processus léger (LWP) doit le faire. être associés à un thread de noyau spécifique, par conséquent :

  • Comme les threads du noyau, ils peuvent pleinement rivaliser et utiliser les ressources du processeur à l'échelle du système ;

    Chaque processus léger (LWP) est une unité de planification de thread indépendante, de sorte que même s'il s'agit d'un thread léger Le processus (LWP) est bloqué dans un appel système, cela n'affectera pas l'exécution de l'ensemble du processus ;
    • Le processus léger (LWP) doit consommer des ressources du noyau (principalement l'espace de la pile des threads du noyau), ce qui rend impossible la prise en charge d'un grand nombre de processus. nombre de processus légers (LWP) dans le système ;
    • peut accéder à tous les espaces d'adressage partagés et aux ressources système du processus auquel il appartient.
  • Résumé

Ci-dessus, nous avons brièvement présenté les types de threads courants (threads d'état du noyau, threads d'état utilisateur, processus légers). Chacun d'eux a son propre champ d'application et peut être utilisé dans le cadre d'une utilisation réelle. combinez-les librement et utilisez-les selon vos propres besoins, tels que les modèles courants un-à-un, plusieurs-à-un, plusieurs-à-plusieurs et autres. En raison des limitations d'espace, cet article n'en parlera pas trop. Les étudiants intéressés peuvent l’étudier par eux-mêmes.

Coroutine

Coroutine, également appelé Fiber, est un mécanisme d'exécution de programme construit sur des threads gérés par les développeurs pour effectuer la planification, la maintenance de l'état et d'autres comportements. Ses principales caractéristiques sont :

Parce que la planification de l'exécution ne nécessite pas. changement de contexte, il a une bonne efficacité d'exécution ;

Parce qu'il s'exécute sur le même thread, il n'y a pas de problème de synchronisation dans la communication des threads ;
  • Commutation pratique du flux de contrôle et modèle de programmation simplifié .
  • En JavaScript, le async/await que nous utilisons souvent est une implémentation de coroutine, comme dans l'exemple suivant :
  • 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;
    }
  • Dans l'exemple ci-dessus, la fonction updateUserName Le logique la séquence d'exécution dans le code> et <code>updateUserNameAsync est :

async/await 便是协程的一种实现,比如下面的例子:

rrreee

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

  • 调用函数 getUserById 并将其返回值赋给变量 user
  • 调用 userupdateName 方法;
  • 返回 true 给调用者。

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

  • 在函数 updateUserName 的执行过程中,按照前文所述的逻辑顺序依次执行;
  • 在函数 updateUserNameAsync 的执行过程中,同样按照前文所述的逻辑顺序依次执行,只不过在遇到 await 时,updateUserNameAsync 将会被挂起并保存挂起位置当前的程序状态,直到 await 后面的程序片段返回后,才会再次唤醒 updateUserNameAsync 并恢复挂起前的程序状态,然后继续执行下一段程序。

通过上面的分析我们可以大胆猜测:协程要解决的并非是进程、线程要解决的程序并发问题,而是要解决处理异步任务时所遇到的问题(比如文件操作、网络请求等);在 async/await 之前,我们只能通过回调函数来处理异步任务,这很容易使我们陷入回调地狱Appelez la fonction getUserById et attribuez sa valeur de retour à la variable user

🎜 Appelez ; la méthode updateName de user ; 🎜🎜renvoie true à l'appelant. 🎜🎜🎜La principale différence entre les deux est le contrôle de l'état pendant le processus en cours d'exécution : 🎜🎜🎜Lors de l'exécution de la fonction updateUserName, elle est exécutée en séquence selon la séquence logique mentionnée ci-dessus ; 🎜🎜Dans la fonction Lors de l'exécution de updateUserNameAsync, elle est également exécutée dans le même ordre logique que celui mentionné ci-dessus, sauf que lorsque await est rencontré, updateUserNameAsync sera Suspend et enregistrera l'état actuel du programme à la position suspendue jusqu'à ce que le fragment du programme après <code>await revienne, updateUserNameAsync sera à nouveau réveillé et l'état du programme avant la suspension. sera restauré, puis passez au programme suivant. 🎜🎜🎜Grâce à l'analyse ci-dessus, nous pouvons deviner avec audace : ce que les coroutines doivent résoudre, ce ne sont pas les problèmes de concurrence de programme que les processus et les threads doivent résoudre, mais les problèmes rencontrés lors du traitement des tâches asynchrones (telles que les opérations sur les fichiers, les requêtes réseau, etc. . ); Avant async/await, nous ne pouvions gérer les tâches asynchrones que via des fonctions de rappel, ce qui pouvait facilement nous faire tomber dans l'l'enfer du rappel, et il serait difficile de produire un tas de merde. Code maintenu, grâce aux coroutines, nous pouvons atteindre l'objectif de synchronisation du code asynchrone. 🎜

Ce qu'il faut garder à l'esprit, c'est que la capacité principale des coroutines est de pouvoir suspendre un certain programme et maintenir l'état de la position suspendue du programme, et de reprendre la position suspendue à un moment donné dans le futur, et continuer à exécuter l'étape suivante après la position suspendue Un programme.

Modèle d'E/S

Une opération E/S complète doit passer par les étapes suivantes : I/O 操作需要经历以下阶段:

  • 用户进(线)程通过系统调用向内核发起 I/O 操作请求;
  • 内核对 I/O 操作请求进行处理(分为准备阶段和实际执行阶段),并将处理结果返回给用户进(线)程。

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

  • 阻塞/非阻塞

    • 如果 A 只有在接收到 B 的响应之后才返回,那么该调用为阻塞调用
    • 如果 A 调用 B 后立即返回(即无需等待 B 执行完毕),那么该调用为非阻塞调用
  • 同步/异步

    • 如果 B 只有在执行完之后再通知 A,那么服务 B 是同步的;
    • 如果 A 调用 B 后,B 立刻给 A 一个请求已接收的通知,然后在执行完之后通过回调的方式将执行结果通知给 A,那么服务 B 就是异步的。

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

  • 阻塞/非阻塞针对于服务的调用者而言;
  • 同步/异步针对于服务的被调用者而言。

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

阻塞 I/O

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

特点:

  • 由于该模型会阻塞用户进(线)程,因此该模型不占用 CPU 资源;
  • 在执行 I/O 操作的时候,用户进(线)程不能进行其它操作;
  • 该模型仅适用于并发量小的应用,这是因为一个 I/O 请求就能阻塞进(线)程,所以为了能够及时响应 I/O 请求,需要为每个请求分配一个进(线)程,这样会造成巨大的资源占用,并且对于长连接请求来说,由于进(线)程资源长期得不到释放,如果后续有新的请求,将会产生严重的性能瓶颈。

非阻塞 I/O

定义:

  • 用户进(线)程发起 I/O 系统调用后,如果该 I/O 操作未准备就绪,该 I/O 调用将会返回一个错误,用户进(线)程也无需等待,而是通过轮询的方式来检测该 I/O 操作是否就绪;
  • 操作就绪后,实际的 I/O 操作会阻塞用户进(线)程直到执行结果返回给用户进(线)程。

特点:

  • 由于该模型需要用户进(线)程不断地询问 I/O 操作就绪状态(一般使用 while 循环),因此该模型需占用 CPU,消耗 CPU 资源;
  • I/O 操作就绪前,用户进(线)程不会阻塞,等到 I/O 操作就绪后,后续实际的 I/O 操作将阻塞用户进(线)程;
  • 该模型仅适用于并发量小,且不需要及时响应的应用。

同(异)步 I/O

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

判断 I/O 操作同步异步的标准是用户进(线)程与 I/O

  • Le processus utilisateur (thread) initie un appel système au demande d'opération E/S du noyau ;
  • Le noyau traite la demande d'opération E/S (divisée en phase de préparation et phase d'exécution réelle) et renvoie le résultat du traitement Donner aux utilisateurs un processus (thread).
Nous pouvons grossièrement diviser les opérations E/S en E/S bloquantes et E/S non bloquantes , E/S synchrones, E/S asynchrones quatre types Avant de discuter de ces types, nous nous familiarisons d'abord avec les deux ensembles de concepts suivants (ici, il est supposé que le service. A appelle le service B) : 🎜
  • 🎜Bloquant/Non bloquant : 🎜
    • Si A revient seulement après avoir reçu la réponse de B, alors l'appel est Appel bloquant;
    • Si A revient immédiatement après avoir appelé B (c'est-à-dire sans attendre que B termine l'exécution), alors l'appel est un appel non bloquant.
  • 🎜Synchrone/asynchrone : 🎜
    • Si B notifie A seulement une fois l'exécution terminée, alors le service B estSynchrone
;
  • Si A appelle B, B informe immédiatement A que la demande a été reçue, puis une fois l'exécution terminée, elle sera appelée via callback Le résultat de l'exécution est notifié à A, alors le service B est <code>asynchrone.
  • 🎜Beaucoup de gens confondent souvent bloquant/non bloquant avec synchrone/asynchrone, une attention particulière est donc requise :🎜
    • Bloquant/non bloquant pour l'appelant du service
    • Synchrone/asynchrone ; > code>Pour l'appelé du service.
    🎜Comprenant le bloquant/non bloquant et le synchrone/asynchrone, regardons le modèle d'E/S spécifique. . 🎜

    🎜Blocage des E/S🎜

    🎜Définition : Une fois que l'utilisateur a lancé l'appel système E/S dans le processus (thread), l'utilisateur entre (le thread) sera immédiatement bloqué jusqu'à ce que l'intégralité de l'opération E/S soit traitée et que le résultat soit renvoyé au thread de l'utilisateur (thread). bloqué et continuez à effectuer les opérations suivantes. 🎜🎜Caractéristiques :🎜
    • Étant donné que ce modèle bloque le processus (thread) de l'utilisateur, ce modèle n'occupe pas de ressources CPU
    • Lors de l'exécution des E/S pendant opération, l'utilisateur ne peut pas effectuer d'autres opérations dans le processus (thread) ;
    • Ce modèle ne convient qu'aux applications avec une faible concurrence, car une requête E/S peut bloquer les entrées ( thread), donc afin de répondre aux requêtes E/S en temps opportun, il est nécessaire d'allouer un thread (thread) entrant pour chaque requête. Cela entraînera une utilisation énorme des ressources, et pour. longues demandes de connexion Par exemple, étant donné que les ressources de processus entrantes (thread) ne peuvent pas être libérées pendant une longue période, s'il y a de nouvelles demandes à l'avenir, un sérieux goulot d'étranglement des performances se produira.

    🎜E/S non bloquantes🎜

    🎜Définition : 🎜
    • Initié par le processus utilisateur (thread)I/O, si l'opération I/O n'est pas prête, l'appel I/O retournera une erreur et l'utilisateur entrera ( Les ​​threads n'ont pas besoin d'attendre, mais utilisent l'interrogation pour détecter si l'opération E/S est prête ;
    • Une fois l'opération prête, le I réel /O L'opération bloque le thread de l'utilisateur jusqu'à ce que le résultat de l'exécution soit renvoyé au thread de l'utilisateur.
    🎜Caractéristiques : 🎜
    • Parce que ce modèle nécessite que l'utilisateur demande en permanence l'état de préparation à l'opération E/S (utilisez généralement while code> boucle), ce modèle doit donc occuper le CPU et consommer les ressources du CPU ;
    • Avant que l'opération E/S ne soit prête, le processus (thread) de l'utilisateur ne sera pas bloqué, une fois l'opération E/S prête, l'opération E/S réelle suivante bloquera le processus (thread) de l'utilisateur ;
    • Ce modèle est uniquement applicable. Il convient aux applications avec une faible concurrence et ne nécessitant pas de réponse rapide.

    🎜E/S synchrones (asynchrones)🎜

    🎜Processus utilisateur lancé E/S Après code> appel système , si l'appel <code>I/O entraînera le blocage du thread (thread) de l'utilisateur, alors l'appel I/O sera E/S synchrone code>, sinon <code>E/S asynchrones. 🎜🎜Le critère pour juger si l'opération E/S est synchrone ou asynchrone est la progression de l'utilisateur (thread) et I/ O Mécanisme de communication pour les opérations, où : 🎜
    • Synchronisation Dans le cas d'un processus utilisateur (thread) et de E/S, l'interaction est synchronisée via le tampon du noyau, c'est-à-dire que le noyau
    Le résultat de l'exécution de l'opération est synchronisé avec le tampon, puis les données dans le tampon sont copiées dans le processus utilisateur (thread). Ce processus bloquera le processus utilisateur (thread) jusqu'à ce que E/S. L'opération est terminée ; 同步情况下用户进(线)程与 I/O 的交互是通过内核缓冲区进行同步的,即内核会将 I/O 操作的执行结果同步到缓冲区,然后再将缓冲区的数据复制到用户进(线)程,这个过程会阻塞用户进(线)程,直到 I/O 操作完成;
  • 异步情况下用户进(线)程与 I/O 的交互是直接通过内核进行同步的,即内核会直接将 I/O 操作的执行结果复制到用户进(线)程,这个过程不会阻塞用户进(线)程。
  • Node.js 的并发模型

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

    • JavaScript 在 V8 下以单线程模式运行,为其实现多线程极其困难;
    • 绝大多数网络应用都是 I/O 密集型的,在保证高并发的情况下,如何合理、高效地管理多线程资源相对于单线程资源的管理更加复杂。

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

    • Node.js 进程启动后,Node.js 主线程会创建一个 EventLoop,EventLoop 的主要作用是注册事件的回调函数并在未来的某个事件循环中执行;
    • Worker 线程用来执行具体的事件任务(在主线程之外的其它线程中以同步方式执行),然后将执行结果返回到主线程的 EventLoop 中,以便 EventLoop 执行相关事件的回调函数。

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

    总结

    Node.js 是前端开发人员现在乃至未来不得不面对的技术,然而大多数前端开发人员对 Node.js 的认知仅停留在表面,为了让大家更好地理解 Node.js 的并发模型,本文先介绍了进程、线程、协程,接着介绍了不同的 I/OAsynchrone Dans le cas du processus utilisateur (thread) et des E/S, l'interaction est directement synchronisée via le noyau, c'est-à-dire , le noyau copiera directement le résultat de l'exécution de l'opération I/O dans le thread utilisateur. Ce processus ne bloquera pas le thread utilisateur.

    Le modèle de concurrence de Node.js

    Node.js utilise un modèle de concurrence à thread unique, piloté par les événements. modèle E/S asynchrone Personnellement, je pense que la raison du choix de ce modèle est la suivante :

    JavaScript fonctionne en mode monothread sous V8, et il est extrêmement difficile d'implémenter le multi-threading La grande majorité des applications réseau sont gourmandes en E/S. Lorsqu'on garantit une concurrence élevée, la gestion raisonnable et efficace des ressources multithread est plus compliquée que la gestion des ressources monothread. En bref, dans un souci de simplicité et d'efficacité, Node.js adopte un modèle E/S asynchrone à thread unique et piloté par événements, et utilise le thread principal EventLoop et les threads Worker auxiliaires pour implémenter son modèle :

    🎜🎜Après le démarrage du processus Node.js, le thread principal Node.js créera un EventLoop. La fonction principale de EventLoop est d'enregistrer la fonction de rappel de l'événement et de l'exécuter. dans une future boucle d'événements ;🎜Le thread Worker est utilisé pour exécuter des tâches événementielles spécifiques (exécutées de manière synchrone dans d'autres threads autres que le thread principal), puis renvoie les résultats de l'exécution à l'EventLoop du thread principal afin que EventLoop peut exécuter des rappels pour la fonction d'événements associés. 🎜Il convient de noter que Node.js n'est pas adapté à l'exécution de tâches gourmandes en CPU (c'est-à-dire nécessitant beaucoup de calculs) en raison du code EventLoop et JavaScript (tâche événementielle non asynchrone) ; code) s'exécutent dans le même thread (c'est-à-dire le thread principal). Si l'un d'entre eux s'exécute trop longtemps, cela peut entraîner le blocage du thread principal. Si l'application contient un grand nombre de tâches nécessitant une exécution longue, cela sera réduit. le débit du serveur et peut même empêcher le serveur de répondre. 🎜

    Résumé

    🎜Node.js est une technologie à laquelle les développeurs front-end doivent faire face maintenant et même à l'avenir. Cependant, la plupart. Les développeurs front-end ne sont pas familiers avec la compréhension de Node.js. Afin de permettre à chacun de mieux comprendre le modèle de concurrence de Node.js, cet article présente d'abord les processus, les threads et les coroutines, puis présente différents. I/O Model, et enfin une brève introduction au modèle de concurrence de Node.js. Bien qu'introduit Il n'y a pas beaucoup d'espace sur le modèle de concurrence Node.js, mais je pense qu'il ne changera jamais sans s'éloigner de ses racines. Une fois que vous maîtriserez les bases pertinentes et que vous comprendrez en profondeur la conception et la mise en œuvre de Node.js, vous obtiendrez deux fois. le résultat avec la moitié de l'effort. 🎜🎜Enfin, s'il y a des erreurs dans cet article, j'espère que vous pourrez les corriger. Je vous souhaite à tous un bon codage chaque jour. 🎜🎜Pour plus de connaissances sur les nœuds, veuillez visiter : 🎜tutoriel Nodejs🎜 ! 🎜

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer