Einführung in Shared Memory in JavaScript
Geteilte Erinnerung ist eine erweiterte Funktion von JavaScript, die Threads (gleichzeitig ausgeführte Teile eines Prozesses) nutzen können. Gemeinsame Nutzung der Speichermittel keine Mühe, aktualisierte Daten zwischen Threads zu übergeben und alle Threads können auf dieselben Daten im gemeinsam genutzten Speicher zugreifen und diese aktualisieren.
Hört sich das nicht gut an? Naja fast. In diesem Beitrag werden wir sehen So verwenden Sie Shared Memory in JavaScript und wie Sie entscheiden, ob Sie das wirklich wollen.
Vorteile und Nachteile des Shared Memory
Wir gebrauchen Web-Arbeiter zu Erstellen Sie Threads in JavaScript. Mit der Web Workers-API können wir Arbeitsthreads erstellen, die verwendet werden können Code im Hintergrund ausführen so dass der Haupt-Thread seine Ausführung fortsetzen kann, möglicherweise UI-Ereignisse verarbeitet und kein Einfrieren der UI sichergestellt wird.
Arbeitsthreads laufen gleichzeitig mit dem Haupt-Thread und untereinander. Eine solche gleichzeitige Ausführung verschiedener Teile einer Aufgabe ist zeitsparend. Sie beenden schneller, haben aber auch ihre eigenen Probleme.
Stellen Sie sicher, dass jeder Thread ruft die notwendigen Ressourcen auf und kommuniziert zeitnah miteinander ist eine Aufgabe an sich, bei der ein Zwischenfall zu einem überraschenden Ergebnis führen kann. Oder wenn Ein Thread ändert Daten und ein anderer liest sie zur selben Zeit, Was glaubst du wird der andere Thread sehen? Die aktualisierten oder die alten Daten?
Web-Worker sind jedoch nicht so leicht zu vermasseln. Während der Kommunikation über Nachrichten verwenden sie die Daten, die sie einander senden nicht original, sondern eine kopie, Das heißt, sie tun es nicht Aktie die gleichen Daten. Sie Kopien von Daten aneinander übergeben wenn gebraucht.
Teilen ist jedoch wichtig, und mehrere Threads müssen möglicherweise gleichzeitig auf dieselben Daten zugreifen und sie ändern. So, Verbot von Teilen ist ein großes Nein. Dies ist, wo die SharedArrayBuffer
Objekt kommt ins Bild. Es wird uns zulassen Binäre Daten zwischen mehreren Threads gemeinsam nutzen.
Das SharedArrayBuffer
Objekt
Anstatt die Datenkopien zwischen Threads zu übergeben, müssen wir Kopien der SharedArrayBuffer
Objekt. EIN SharedArrayBuffer
Objekt zeigt auf den Speicher, in dem die Daten gespeichert werden.
Also auch bei den Kopien von SharedArrayBuffer
werden zwischen Threads weitergegeben Alle zeigen immer noch auf dieselbe Erinnerung wo die ursprünglichen Daten gespeichert werden. Die Fäden können also Anzeigen und Aktualisieren der Daten in demselben Speicher.
Web-Arbeiter ohne geteilte Erinnerung
Um zu sehen, wie ein Web-Worker funktioniert, ohne Shared Memory zu verwenden, haben wir Erstellen Sie einen Arbeitsthread und Daten übergeben.
Das index.html
Datei enthält die Hauptskript in einem tag, wie du unten sehen kannst:
const w = new Worker ('worker.js'); var n = 9; w.postMessage (n);
Das worker.js
Datei trägt die Arbeiterskript:
onmessage = (e) => console.group ('[worker]'); console.log ('Daten vom Haupt-Thread erhalten:% i', e.data); console.groupEnd ();
Mit dem obigen Code erhalten wir Folgendes Ausgabe in der Konsole:
[Arbeiter] Daten aus dem Hauptthread erhalten: 9
Sie können meinen oben genannten Beitrag auf Web Workern lesen, um die vollständige Code-Erklärung für die obigen Ausschnitte zu erhalten.
Denken Sie im Moment daran, dass dies Daten sind hin und her zwischen den Threads Verwendung der POST-Meldung()
Methode. Die Daten sind auf der anderen Seite von der Botschaft
Eventhandler, als Wert der Veranstaltung Daten
Eigentum.
Nun, wenn wir Ändern Sie die Daten erscheint es auf der empfangenden Seite aktualisiert? Mal schauen:
const w = new Worker ('worker.js'); var n = 9; w.postMessage (n); n = 1;
Wie erwartet die Daten haben nicht aktualisiert worden:
[Arbeiter] Daten aus dem Hauptthread erhalten: 9
Warum sollte es überhaupt so sein? Es ist Nur ein Klon aus dem Hauptskript an den Arbeiter gesendet.
Web-Arbeiter mit geteilte Erinnerung
Jetzt werden wir benutze die SharedArrayBuffer
Objekt im gleichen Beispiel. Wir können ein neues schaffen SharedArrayBuffer
Beispiel von Verwendung der Neu
Stichwort. Der Konstruktor hat einen Parameter. ein Längenwert in Bytes, Angabe der Größe des Puffers.
const w = new Worker ('worker.js'); buff = new SharedArrayBuffer (1); var arr = new Int8Array (Buff); / * Einstellungsdaten * / arr [0] = 9; / * Senden des Puffers (Kopie) an Worker * / w.postMessage (Buff);
Beachten Sie, dass a SharedArrayBuffer
Objekt repräsentiert nur einen gemeinsam genutzten Speicherbereich. Zu sehen und ändern Sie die binären Daten, Wir müssen eine geeignete Datenstruktur verwenden (a TypedArray
oder ein Datenansicht
Objekt).
In dem index.html
Datei oben, eine neue SharedArrayBuffer
wird nur mit einer Länge von einem Byte erstellt. Dann ein neues Int8Array
, Welches ist eine Art von TypedArray
Objekte, ist es gewohnt Setze die Daten auf “9” im bereitgestellten Byte-Bereich.
onmessage = (e) => var arr = new Int8Array (e.data); console.group ('[worker]'); console.log ('Daten vom Haupt-Thread erhalten:% i', arr [0]); console.groupEnd ();
Int8Array
wird auch im Arbeiter verwendet, um die Daten im Puffer anzeigen.
Das Der erwartete Wert wird in der Konsole angezeigt aus dem Arbeitsthread, das ist genau das, was wir wollten:
[Arbeiter] Daten aus dem Hauptthread erhalten: 9
Jetzt lass uns Aktualisieren Sie die Daten im Hauptthread um zu sehen, ob sich die Änderung im Arbeiter widerspiegelt.
const w = new Worker ('worker.js'), buff = neuer SharedArrayBuffer (1); var arr = new Int8Array (Buff); / * Einstellungsdaten * / arr [0] = 9; / * Senden des Puffers (Kopie) an Worker * / w.postMessage (Buff); / * Ändern der Daten * / arr [0] = 1;
Und wie Sie unten sehen können, das Update reflektiert sich im Inneren des Arbeiters!
[Arbeiter] Daten aus dem Hauptthread erhalten: 1
Aber der Code auch muss andersherum arbeiten: Wenn sich der Wert im Worker zuerst ändert, dann muss auch aktualisiert werden wenn es aus dem Hauptfaden gedruckt wird.
In diesem Fall sieht unser Code so aus:
onmessage = (e) => var arr = new Int8Array (e.data); console.group ('[worker]'); console.log ('Daten vom Haupt-Thread erhalten:% i', arr [0]); console.groupEnd (); / * Ändern der Daten * / arr [0] = 7; / * Beitrag zum Hauptthread * / postMessage (");
Das Daten werden im Worker geändert und ein Eine leere Nachricht wird an den Hauptthread gesendet signalisiert, dass die Daten im Puffer geändert wurden und für die Ausgabe des Haupt-Threads bereit sind.
const w = new Worker ('worker.js'), buff = neuer SharedArrayBuffer (1); var arr = new Int8Array (Buff); / * Einstellungsdaten * / arr [0] = 9; / * Senden des Puffers (Kopie) an Worker * / w.postMessage (Buff); / * Ändern der Daten * / arr [0] = 1; / * Drucken der Daten, nachdem der Mitarbeiter sie geändert hat * / w.onmessage = (e) => console.group ('[main]'); console.log ('Aktualisierte Daten vom Arbeitsthread erhalten:% i', arr [0]); console.groupEnd ();
Und das funktioniert auch! Die Daten im Puffer sind die gleichen wie die Daten im Worker.
[Arbeiter] Daten vom Hauptthread erhalten: 1 [Haupt] Aktualisierte Daten vom Arbeitsthread: 7
Der Wert erscheint in beiden Fällen aktualisiert; Sowohl der Haupt- als auch der Arbeitsthread sehen und ändern dieselben Daten.
Letzte Worte
Wie bereits erwähnt, verwenden Sie Shared Memory in JavaScript ist nicht ohne Nachteile. Es liegt an den Entwicklern, sicherzustellen, dass die Ablauf der Ausführung erfolgt wie vorhergesagt und keine zwei Threads kämpfen um die gleichen Daten, weil niemand weiß, wer die Trophäe nehmen wird.
Wenn Sie sich für Shared Memory interessieren, schauen Sie in die Dokumentation des Atomik
Objekt. Das Atomics-Objekte können Ihnen bei einigen Schwierigkeiten helfen, durch Verringern der unvorhersehbaren Art des Lesens / Schreibens aus dem gemeinsam genutzten Speicher.