Heim  >  Artikel  >  Web-Frontend  >  Verstehen Sie den einzelnen Thread von JavaScript wirklich?

Verstehen Sie den einzelnen Thread von JavaScript wirklich?

WBOY
WBOYnach vorne
2022-01-10 19:08:012320Durchsuche

Dieser Artikel vermittelt Ihnen Wissen über unseren JavaScript-Single-Thread. Warum kann JavaScript einen Timer und eine Funktion gleichzeitig ausführen?

Verstehen Sie den einzelnen Thread von JavaScript wirklich?

1. Prozesse und Threads Planung im System, die die Grundlage der Betriebssystemstruktur bildet. In der modernen, für Threads konzipierten Computerarchitektur sind Prozesse Container für Threads. Ein Programm ist eine Beschreibung von Anweisungen, Daten und deren Organisation, und ein Prozess ist die Einheit des Programms. Es handelt sich um eine laufende Aktivität eines Programms in einem Computer für einen bestimmten Datensatz. Es ist die Grundeinheit der Ressourcenzuweisung und -planung im System und die Grundlage der Betriebssystemstruktur. Ein Programm ist eine Beschreibung von Anweisungen, Daten und deren Organisation, und ein Prozess ist die Einheit des Programms. Wir vergleichen den Prozess hier mit der Werkstatt einer Fabrik, die eine einzelne Aufgabe darstellt, die die CPU bewältigen kann. Zu jedem Zeitpunkt führt die CPU immer einen Prozess aus, und andere Prozesse befinden sich in einem nicht ausgeführten Zustand.

1.2 Thread

ist die kleinste Einheit, die das Betriebssystem zur Berechnungsplanung durchführen kann. Es wird in den Prozess eingebunden und ist die eigentliche Bedieneinheit im Prozess. Ein Thread bezieht sich auf einen einzelnen sequenziellen Kontrollfluss in einem Prozess. In einem Prozess können mehrere Threads gleichzeitig ausgeführt werden, und jeder Thread führt parallel unterschiedliche Aufgaben aus.

Hier werden Threads mit Arbeitern in einer Werkstatt verglichen, das heißt, in einer Werkstatt können mehrere Arbeiter zusammenarbeiten, um eine Aufgabe zu erledigen.

2. Multithread-Browser

Unter der Kontrolle des Kernels kooperiert jeder Thread miteinander, um die Synchronisation aufrechtzuerhalten:

GUI-Rendering-Thread

JavaScript-Engine-Thread

  • Event-Trigger-Thread

  • Timed-Trigger-Thread

  • Asynchroner HTTP-Anfrage-Thread

  • Wir haben gesehen der JS-Engine-Thread, der sehr ist vertraut. Nichts falsch, hier führen wir das Javascript-Skriptprogramm aus.

    Die JS-Engine ist Multi-Threading, was bedeutet, dass die JS-Engine nur einen Thread für die Ausführung zuweist, wenn sie JS ausführt. Das bedeutet, dass die JS-Engine einen Thread für die Ausführung von JavaScript zuweist, was wir als Single-Threading bezeichnen .

2.1 Lassen Sie uns hier über den Ausführungsmechanismus von JS sprechenVerstehen Sie den einzelnen Thread von JavaScript wirklich?

Da JavaScript Single-Threaded ist (es gibt immer nur einen JS-Thread, der das JavaScript-Programm auf einer Tab-Seite ausführt).

Wir müssen uns also auf die Aufgabenwarteschlange verlassen, um JavaScript-Code auszuführen.

Die JS-Engine wartet immer auf das Eintreffen von Aufgaben in der Aufgabenwarteschlange und führt die Aufgaben dann aus. Natürlich ist es kein Problem, Synchronisierungsaufgaben auf diese Weise auszuführen. Wir stellen die Aufgaben in die Aufgabenwarteschlange und führen sie einzeln aus. Die Logik ist sehr klar. Wenn wir jedoch eine Anfrage an den Hintergrund senden, kann die Zeit zwischen Senden und Empfangen eine Sekunde dauern. Wenn wir fünfmal eine Anfrage stellen, dann fünf Sekunden warten. Die Anzeige entspricht nicht unseren Anforderungen, daher benötigen wir eine asynchrone Aufgabe, um dieses Problem zu lösen.

2.2 Synchrone Aufgaben und asynchrone Aufgaben

Synchrone Aufgaben beziehen sich auf Aufgaben, die zur Ausführung im Hauptthread in die Warteschlange gestellt werden. Erst wenn die vorherige Aufgabe ausgeführt wird, kann der Rendervorgang fortgesetzt werden Website, Beispielsweise ist das Rendern von Elementen tatsächlich eine synchrone Aufgabe.

Asynchrone Aufgaben beziehen sich auf Aufgaben, die nicht in den Hauptthread, sondern nur dann in die Aufgabenwarteschlange gelangen, wenn die Aufgabenwarteschlange den Hauptthread benachrichtigt, dass eine asynchrone Aufgabe ausgeführt werden kann Wird die Aufgabe in den Hauptthread aufgenommen, ist das Laden von Bildern und Musik tatsächlich eine asynchrone Aufgabe.

Jeder muss ein konkreteres Verständnis von Event Loop haben. Ich werde hier nicht auf Details eingehen. Wenn Sie es nicht verstehen, können Sie es mir sagen und ich werde es noch einmal erklären.

3. Dieser Artikel konzentriert sich auf die wichtigsten Punkte – Sie können ihn direkt lesen

Aber haben Sie Fragen zur Aufgabenwarteschlange? Ist das ein Objekt? Ist es ein Array? Nach meiner Logik führt unser JavaScript-Hauptthread synchrone Funktionen aus, und asynchrone Funktionen können in die Aufgabenwarteschlange gestellt werden. Wenn wir mit der Ausführung der synchronen Aufgabe fertig sind, schieben Sie dieses Objekt (Aufgabenwarteschlange) in die Hauptwarteschlange Im Thread ist alles in Ordnung, aber es ist nicht das, was ich gedacht habe.

Die Aufgabenwarteschlange von Evnet Loop wird im ereignisauslösenden Thread des Browsers platziert. Wenn die JS-Engine eine asynchrone Funktion ausführt, platziert sie die asynchrone Aufgabe im ereignisauslösenden Thread Der ereignisauslösende Thread fügt die asynchrone Aufgabe am Ende der Warteschlange des Hauptthreads in der JS-Engine hinzu und wartet auf die Ausführung.

Unterscheidet es sich von dem Single-Threaded-JavaScript, das wir uns vorgestellt haben? Nun, es ist wirklich nicht dasselbe, daher ist die endgültige Schlussfolgerung, dass es sich bei der Aufgabenwarteschlange, über die wir sprechen, tatsächlich um einen Thread handelt. Wenn wir dann auf den Timer zurückkommen, über den wir gerade am Anfang gesprochen haben, können Sie im Grunde davon ausgehen, dass er vom Timer-Thread gesteuert wird.

Da es sich bei JavaScript um einen Single-Thread handelt, beeinträchtigt es die Genauigkeit des Timings, wenn es sich in einem blockierten Thread-Status befindet. Daher ist es erforderlich, einen separaten Thread für das Timing zu öffnen.

Bei Verwendung von setTimeout oder setInterval ist ein Timer-Thread-Timing erforderlich. Nach Abschluss des Timings wird das spezifische Ereignis in die Ereigniswarteschlange verschoben.

4. Fazit

Wir sagen also, dass JavaScript Single-Threaded ist, auch wenn der King of Heaven kommt, aber unsere Ereignisschleife und unser Timer sind in anderen Threads platziert.

5. V8-Engine – Erweiterung

V8-Engine ist eine JavaScript-Engine-Implementierung, die ursprünglich von einigen Sprachexperten entworfen und später von Google erworben und dann als Open Source bereitgestellt wurde.

V8 wird mit C++ entwickelt. Im Gegensatz zu anderen JavaScript-Engines, die es in Bytecode konvertieren oder zur Ausführung interpretieren, kompiliert V8 es in nativen Maschinencode (IA-32-, x86-64-, ARM- oder MIPS-CPUs). , und Methoden wie Inline-Caching werden verwendet, um die Leistung zu verbessern.

Mit diesen Funktionen laufen JavaScript-Programme genauso schnell wie Binärprogramme unter der V8-Engine. V8 unterstützt viele Betriebssysteme wie Windows, Linux, Android usw. sowie andere Hardwarearchitekturen wie IA32, X64, ARM usw. und verfügt über gute Portabilität und plattformübergreifende Funktionen.

5.1 Arbeitsablauf

Der Prozess der Ausführung von JavaScript durch die V8-Engine besteht aus zwei Hauptphasen: Kompilierung und Ausführung. Im Gegensatz zu C++, das vor der Ausführung vollständig kompiliert wird, muss JavaScript kompiliert und ausgeführt werden, wenn der Benutzer es verwendet. In V8 wird JavaScript-bezogener Code nicht auf einmal kompiliert, sondern erst dann, wenn bestimmte Codes ausgeführt werden müssen, was die Reaktionszeit verbessert und den Zeitaufwand reduziert. In der V8-Engine wird der Quellcode zunächst vom Parser in einen abstrakten Syntaxbaum (AST) konvertiert, und dann wird der vollständige Codegenerator des JIT-Compilers verwendet, um direkt lokalen ausführbaren Code aus dem AST zu generieren. Dieser Prozess unterscheidet sich von JAVAs erster Generation von Bytecode oder Zwischendarstellung, wodurch die Konvertierungszeit von AST in Bytecode verkürzt und die Codeausführungsgeschwindigkeit verbessert wird. Aufgrund des fehlenden Zwischenprozesses der Konvertierung in Bytecode ist jedoch die Möglichkeit zur Optimierung des Codes geringer.

Die von der V8-Engine beim Kompilieren von lokalem Code verwendeten Hauptklassen sind wie folgt:

  • Skript: Stellt JavaScript-Code dar, der Quellcode und lokalen Code enthält, der nach der Kompilierung generiert wird, also den Kompilierungseintrag und den laufenden Eintrag

  • Compiler: Compiler-Klasse, Hilfsgruppe Skriptklasse zum Kompilieren und Generieren von Code, Aufruf des Interpreters (Parser) zum Generieren von AST und vollständigem Codegenerator, Konvertieren von AST in lokalen Code;

  • AstNode: abstrakter Syntaxbaum Die Knotenklasse ist die Basisklasse für alle anderen Knoten und enthält später verschiedene lokale Codes für verschiedene Unterklassen

  • FullCodeGenerator: eine Unterklasse der AstVisitor-Klasse, die durch Durchlaufen des AST lokalen ausführbaren Code für JavaScript generiert.

  • Der Prozess der JavaScript-Codekompilierung ist ungefähr wie folgt: Die Script-Klasse ruft die Compile-Funktion der Compiler-Klasse auf, um lokalen Code dafür zu generieren. Die Compile-Funktion verwendet zunächst die Parser-Klasse, um AST zu generieren, und verwendet dann die FullCodeGenerator-Klasse, um lokalen Code zu generieren. Nativer Code hängt eng mit der jeweiligen Hardwareplattform zusammen, und FullCodeGenerator verwendet mehrere Backends, um nativen Assemblercode zu generieren, der zur Plattform passt. Da FullCodeGenerator durch Durchlaufen des AST den entsprechenden Assemblercode für jeden Knoten generiert, fehlt die globale Ansicht und eine Optimierung zwischen Knoten ist nicht möglich

Das obige ist der detaillierte Inhalt vonVerstehen Sie den einzelnen Thread von JavaScript wirklich?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.im. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen