Parallelität und Multithreading in JavaScript: Fortgeschrittenes Niveau

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Parallelität und Multithreading in JavaScript: Fortgeschrittenes Niveau



JavaScript war historisch gesehen eine Single-Thread-Sprache, die im Rahmen der Ereignisschleife (Event Loop) arbeitet. Moderne Anwendungen auf Node.js erfordern jedoch eine hohe Leistung bei der Verarbeitung CPU-intensiver Aufgaben. In diesem Artikel werden wir fortgeschrittene Mechanismen der Parallelität und des Multithreadings untersuchen: Worker Threads, SharedArrayBuffer, Atomics und Clustering. Sie erfahren, wie Sie Mehrkernprozessoren effektiv nutzen und Blockierungen des Hauptthreads vermeiden.



1. Worker Threads: Echtes Multithreading in Node.js



Das Modul worker_threads wurde in Node.js 10.5.0 eingeführt und ermöglicht die Erstellung separater Threads mit eigener V8-Engine. Im Gegensatz zum Clustering (Prozesse) teilen sich Worker Threads den Speicher und können Daten über SharedArrayBuffer austauschen.



Erstellen und Starten eines Workers



// main.jsconst { Worker } = require('worker_threads');

function runWorker(data) { return new Promise((resolve, reject) => { const worker = new Worker('./worker.js', { workerData: data }); worker.on('message', resolve); worker.on('error', reject); worker.on('exit', (code) => { if (code !== 0) reject(new Error(`Worker mit Exit-Code ${code} gestoppt`)); }); });}

(async () => { const result = await runWorker({ numbers: [1, 2, 3, 4, 5] }); console.log('Ergebnis:', result); // { sum: 15 }})();


// worker.jsconst { parentPort, workerData } = require('worker_threads');

const sum = workerData.numbers.reduce((acc, val) => acc + val, 0);parentPort.postMessage({ sum });


Wichtig: Worker haben keinen Zugriff auf das DOM oder Module, die den Hauptthread erfordern. Verwenden Sie sie für schwere Berechnungen, Bildverarbeitung oder Verschlüsselung.



2. SharedArrayBuffer und Atomics: Gemeinsam genutzter Speicher



SharedArrayBuffer ermöglicht mehreren Workern das Lesen und Schreiben von Daten in denselben Speicherbereich. Zur Synchronisation des Zugriffs wird das Objekt Atomics verwendet – es garantiert atomare Operationen.



Beispiel: Parallele Verarbeitung eines Arrays



// main.jsconst { Worker } = require('worker_threads');const { SharedArrayBuffer } = require('worker_threads');

const buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 10);const array = new Int32Array(buffer);

// Array füllenfor (let i = 0; i < 10; i++) array[i] = i;

const worker1 = new Worker('./worker_atomics.js', { workerData: { start: 0, end: 5 } });const worker2 = new Worker('./worker_atomics.js', { workerData: { start: 5, end: 10 } });

worker1.on('message', () => console.log('Worker 1 abgeschlossen'));worker2.on('message', () => console.log('Worker 2 abgeschlossen'));


// worker_atomics.jsconst { parentPort, workerData } = require('worker_threads');const { Atomics } = require('worker_threads');

const buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 10);const array = new Int32Array(buffer);

// Atomare Erhöhung jedes Elementsfor (let i = workerData.start; i < workerData.end; i++) { Atomics.add(array, i, 10);}

parentPort.postMessage('done');


Hinweis: Verwenden Sie Atomics.wait() und Atomics.notify() zur Synchronisation von Threads (Analogon zu Mutexen). Dies ist entscheidend, um Wettlaufsituationen (Race Conditions) zu verhindern.



3. Clustering: Skalierung durch Prozesse



Das Modul cluster erstellt mehrere Node.js-Prozesse (Worker), von denen jeder Anfragen verarbeitet. Dies ist die Standardmethode zur Skalierung von HTTP-Servern auf Mehrkernsystemen.



Beispiel: Geclusterter HTTP-Server



const cluster = require('cluster');const http = require('http');const numCPUs = require('os').cpus().length;

if (cluster.isMaster) { console.

Blogs

Buchempfehlungen