Concurrence et multithreading en JavaScript : niveau avancé

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Concurrence et multithreading en JavaScript : niveau avancé



JavaScript a historiquement été un langage monothread fonctionnant dans le cadre de la boucle d'événements (Event Loop). Cependant, les applications modernes sur Node.js nécessitent des performances élevées pour le traitement des tâches intensives en CPU. Dans cet article, nous allons analyser les mécanismes avancés de concurrence et de multithreading : Worker Threads, SharedArrayBuffer, Atomics et le clustering. Vous apprendrez à utiliser efficacement les processeurs multicœurs et à éviter le blocage du thread principal.



1. Worker Threads : le véritable multithreading dans Node.js



Le module worker_threads est apparu dans Node.js 10.5.0 et permet de créer des threads séparés avec leur propre moteur V8. Contrairement au clustering (processus), les Worker Threads partagent la mémoire et peuvent échanger des données via SharedArrayBuffer.



Création et exécution d'un worker



// 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 stopped with exit code ${code}`)); }); });}

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


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

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


Important : Les workers n'ont pas accès au DOM ni aux modules nécessitant le thread principal. Utilisez-les pour les calculs lourds, le traitement d'images ou le chiffrement.



2. SharedArrayBuffer et Atomics : mémoire partagée



SharedArrayBuffer permet à plusieurs workers de lire et d'écrire des données dans une même zone mémoire. Pour synchroniser l'accès, l'objet Atomics est utilisé — il garantit des opérations atomiques.



Exemple : traitement parallèle d'un tableau



// 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);

// Remplir le tableaufor (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 terminé'));worker2.on('message', () => console.log('Worker 2 terminé'));


// 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);

// Incrémentation atomique de chaque élémentfor (let i = workerData.start; i < workerData.end; i++) { Atomics.add(array, i, 10);}

parentPort.postMessage('done');


Remarque : Utilisez Atomics.wait() et Atomics.notify() pour la synchronisation des threads (équivalent des mutex). C'est essentiel pour éviter les conditions de course.



3. Clustering : mise à l'échelle via les processus



Le module cluster crée plusieurs processus Node.js (workers), chacun traitant les requêtes. C'est la méthode standard pour mettre à l'échelle les serveurs HTTP sur les systèmes multicœurs.



Exemple : serveur HTTP en cluster



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

if (cluster.isMaster) { console.

Blogs

Book Recommendations