Maison  >  Article  >  interface Web  >  Comprenez-vous vraiment le thread unique de JavaScript ?

Comprenez-vous vraiment le thread unique de JavaScript ?

WBOY
WBOYavant
2022-01-10 19:08:012322parcourir

Cet article vous apporte des connaissances sur notre JavaScript monothread. JavaScript est un langage monothread. Pourquoi JavaScript peut-il exécuter une minuterie et une fonction en même temps ?

Comprenez-vous vraiment le thread unique de JavaScript ?

1. Processus et fils de discussion

1.1 Processus (Process)

est une activité en cours d'exécution d'un programme dans l'ordinateur sur une certaine collection de données et constitue l'unité de base de l'allocation des ressources et planification dans le système, qui est la base de la structure du système d'exploitation. Dans l'architecture informatique contemporaine conçue pour les threads, les processus sont des conteneurs pour les threads. Un programme est une description d'instructions, de données et de leur organisation, et un processus est l'entité du programme. Il s'agit d'une activité en cours d'exécution d'un programme dans un ordinateur sur un certain ensemble de données. C'est l'unité de base d'allocation et de planification des ressources dans le système et la base de la structure du système d'exploitation. Un programme est une description d'instructions, de données et de leur organisation, et un processus est l'entité du programme.

Nous comparons ici le processus à l'atelier d'une usine, qui représente une tâche unique que le CPU peut gérer. À tout moment, le processeur exécute toujours un processus et les autres processus sont dans un état non exécuté.

1.2 Thread

est la plus petite unité que le système d'exploitation peut effectuer la planification des calculs. Il est inclus dans le processus et constitue la véritable unité opérationnelle du processus. Un thread fait référence à un seul flux de contrôle séquentiel dans un processus. Plusieurs threads peuvent s'exécuter simultanément dans un processus et chaque thread exécute différentes tâches en parallèle.

Ici, les fils de discussion sont comparés aux travailleurs d'un atelier, c'est-à-dire qu'un atelier peut permettre à plusieurs travailleurs de collaborer pour accomplir une tâche.

2. Navigateur multithread

Le noyau du navigateur est multithread, sous le contrôle du noyau, chaque thread coopère entre eux pour maintenir la synchronisation. Un navigateur se compose généralement des threads résidents suivants :

  • . Fil de rendu GUI le fil du moteur JS, qui est très familier. Rien de mal, c'est ici que nous exécutons le programme de script javascript.

    Le moteur JS est multithread. Le moteur JS n'alloue qu'un seul thread pour l'exécution lorsqu'il exécute JS. Cela signifie que le moteur JS alloue un thread pour l'exécution de JavaScript, ce que nous appelons un seul thread. .
  • 2.1 Parlons ici du mécanisme d'exécution de JS

  • Parce que JavaScript est monothread (il n'y a qu'un seul thread JS exécutant le programme JavaScript dans une page à onglet à tout moment).

    Nous devons donc nous appuyer sur la file d'attente des tâches pour exécuter le code JavaScript.
  • Le moteur JS attendra toujours l'arrivée des tâches dans la file d'attente des tâches, puis exécutera les tâches.

    Bien sûr, il n'y a aucun problème à exécuter les tâches de synchronisation de cette manière. Nous mettons toutes les tâches dans la file d'attente des tâches et les exécutons une par une. Cependant, si nous envoyons une demande en arrière-plan, le temps entre l'envoi et la réception peut prendre une seconde. Nous ne pouvons pas l'attendre une seconde. Si nous demandons cinq fois, alors attendez cinq secondes. L'affichage ne répond pas à nos besoins, nous avons donc besoin d'une tâche asynchrone pour gérer ce problème.
  • 2.2 Tâches synchrones et tâches asynchrones

Les tâches synchrones font référence aux tâches mises en file d'attente pour être exécutées sur le thread principal. Ce n'est que lorsque la tâche précédente est exécutée que la tâche suivante peut être poursuivie. Lorsque nous ouvrons le site Web, le processus de rendu du processus de rendu. site Web, Par exemple, le rendu des éléments est en fait une tâche synchrone

Comprenez-vous vraiment le thread unique de JavaScript ?Les tâches asynchrones font référence aux tâches qui n'entrent pas dans le thread principal mais entrent dans la file d'attente des tâches uniquement lorsque la file d'attente des tâches informe le thread principal qu'une tâche asynchrone peut être exécutée. la tâche entrera-t-elle dans le fil principal, lorsque nous ouvrirons le site Web, le chargement des images et de la musique est en fait une tâche asynchrone.

Tout le monde doit avoir une compréhension plus concrète d'Event Loop. Je n'entrerai pas dans les détails ici. Si vous ne comprenez pas, vous pouvez me le dire et je vous l'expliquerai à nouveau.

3. Cet article se concentre sur les points clés - vous pouvez le lire directement

Mais avez-vous des questions sur la file d'attente des tâches ? Est-ce un objet ? Est-ce un tableau ? Selon ma logique, notre thread principal JavaScript exécute des fonctions synchrones et les fonctions asynchrones peuvent être placées dans la file d'attente des tâches. Cette file d'attente des tâches peut être un objet lorsque nous avons fini d'exécuter la tâche synchrone, poussez cet objet (file d'attente des tâches) dans la file d'attente principale. fil. C'est bien dans le fil, mais ce n'est pas ce que je pensais.

La file d'attente des tâches d'Evnet Loop est placée dans le thread de déclenchement d'événements du navigateur Lorsque le moteur JS exécute une fonction asynchrone, il placera la tâche asynchrone dans le thread de déclenchement d'événements lorsque la tâche asynchrone correspondante répond aux conditions de déclenchement et est déclenchée. Le thread déclencheur d'événement ajoutera la tâche asynchrone à la fin de la file d'attente du thread principal dans le moteur JS, en attente d'exécution.

Est-ce différent du JavaScript monothread que nous imaginions ? Eh bien, ce n'est vraiment pas la même chose, donc la conclusion finale est que la file d'attente de tâches dont nous parlons est en fait un thread.

Ensuite, en revenant au timer dont nous avons parlé au début, vous pouvez en gros deviner qu'il est contrôlé par le thread du timer.

Étant donné que JavaScript est monothread, s'il est dans un état de thread bloqué, cela affectera la précision du timing, il est donc nécessaire d'ouvrir un thread séparé pour le timing.

Lors de l'utilisation de setTimeout ou setInterval, cela nécessite une synchronisation du thread de minuterie. Une fois la synchronisation terminée, l'événement spécifique sera poussé dans la file d'attente des événements.

4. Conclusion

Donc, nous disons que JavaScript est monothread, même si le Roi du Ciel arrive, mais notre boucle d'événement et notre minuterie sont placées dans d'autres threads.

5. Moteur V8 - extension

Le moteur V8 est une implémentation de moteur JavaScript, conçue à l'origine par des experts en langage, puis acquise par Google, qui l'a ensuite open source.

V8 est développé en C++. Avant d'exécuter JavaScript, par rapport à d'autres moteurs JavaScript qui le convertissent en bytecode ou l'interprètent pour l'exécution, V8 le compile en code machine natif (CPU IA-32, x86-64, ARM ou MIPS). , et des méthodes telles que la mise en cache en ligne sont utilisées pour améliorer les performances.

Avec ces fonctionnalités, les programmes JavaScript s'exécutent aussi vite que les programmes binaires sous le moteur V8. V8 prend en charge de nombreux systèmes d'exploitation, tels que Windows, Linux, Android, etc., ainsi que d'autres architectures matérielles, telles que IA32, X64, ARM, etc., et possède une bonne portabilité et des fonctionnalités multiplateformes.

5.1 Workflow

Il y a deux étapes principales dans le processus d'exécution de JavaScript par le moteur V8 : la compilation et l'exécution Contrairement au C++ qui est entièrement compilé avant l'exécution, JavaScript doit être compilé et exécuté lorsque l'utilisateur l'utilise. Dans la V8, le code lié à JavaScript n'est pas compilé en une seule fois, mais est compilé lorsque certains codes doivent être exécutés, ce qui améliore le temps de réponse et réduit la surcharge de temps. Dans le moteur V8, le code source est d'abord converti en un arbre de syntaxe abstraite (AST) par l'analyseur, puis le générateur de code complet du compilateur JIT est utilisé pour générer directement du code exécutable local à partir de l'AST. Ce processus est différent de la première génération de bytecode ou de représentation intermédiaire de JAVA, qui réduit le temps de conversion d'AST en bytecode et améliore la vitesse d'exécution du code. Cependant, en raison de l'absence de processus intermédiaire de conversion en bytecode, la possibilité d'optimiser le code est réduite.

Les principales classes utilisées par le moteur V8 lors de la compilation du code local sont les suivantes :

  • Script : représente le code JavaScript, qui comprend le code source et le code local généré après la compilation, qui est l'entrée de compilation et l'entrée en cours d'exécution

    ;
  • Compilateur : classe de compilateur, groupe auxiliaire Classe de script pour compiler et générer du code, appeler l'interpréteur (Parser) pour générer AST et générateur de code complet, convertir AST en code local

  • AstNode : arbre de syntaxe abstraite La classe de nœuds ; est la classe de base pour tous les autres nœuds et contient de nombreuses sous-classes. Différents codes locaux seront générés ultérieurement pour différentes sous-classes

  • AstVisitor : la classe visiteur de l'arbre de syntaxe abstraite, principalement utilisée pour parcourir différents arbres de syntaxe abstraite structurée ;

  • FullCodeGenerator : une sous-classe de la classe AstVisitor, qui génère du code exécutable local pour JavaScript en traversant l'AST.

Comprenez-vous vraiment le thread unique de JavaScript ?

Le processus de compilation du code JavaScript est à peu près le suivant : la classe Script appelle la fonction Compile de la classe Compiler pour générer du code local pour celui-ci. La fonction Compile utilise d'abord la classe Parser pour générer AST, puis utilise la classe FullCodeGenerator pour générer du code local. Le code natif est étroitement lié à la plate-forme matérielle spécifique et FullCodeGenerator utilise plusieurs backends pour générer du code assembleur natif qui correspond à la plate-forme. Étant donné que FullCodeGenerator génère le code d'assemblage correspondant pour chaque nœud en parcourant l'AST, la vue globale est manquante et l'optimisation entre les nœuds est impossible

[Recommandations associées :

Tutoriel d'apprentissage Javascript]

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