JavaScript中的并发与多线程:进阶水平
JavaScript历史上是一种单线程语言,在事件循环(Event Loop)框架内运行。然而,现代Node.js应用程序在处理CPU密集型任务时需要高性能。在本文中,我们将深入探讨并发和多线程的高级机制:Worker Threads、SharedArrayBuffer、Atomics和集群化。您将学习如何有效利用多核处理器并避免阻塞主线程。
1. Worker Threads:Node.js中的真正多线程
worker_threads模块出现在Node.js 10.5.0中,允许创建具有独立V8引擎的单独线程。与集群化(进程)不同,Worker Threads共享内存,并可以通过SharedArrayBuffer交换数据。
创建和启动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('结果:', result); // { sum: 15 }})();// worker.jsconst { parentPort, workerData } = require('worker_threads');
const sum = workerData.numbers.reduce((acc, val) => acc + val, 0);parentPort.postMessage({ sum });重要提示:Worker无法访问DOM或需要主线程的模块。请将它们用于繁重计算、图像处理或加密操作。
2. SharedArrayBuffer和Atomics:共享内存
SharedArrayBuffer允许多个worker读取和写入同一内存区域的数据。为了同步访问,使用Atomics对象——它保证原子操作。
示例:并行数组处理
// 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);
// 填充数组for (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 完成'));worker2.on('message', () => console.log('Worker 2 完成'));// 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);
// 原子增加每个元素for (let i = workerData.start; i < workerData.end; i++) { Atomics.add(array, i, 10);}
parentPort.postMessage('done');注意:使用Atomics.wait()和Atomics.notify()进行线程同步(类似于互斥锁)。这对于防止竞态条件至关重要。
3. 集群化:通过进程进行扩展
cluster模块创建多个Node.js进程(worker),每个进程处理请求。这是在多核系统上扩展HTTP服务器的标准方法。
示例:集群化的HTTP服务器
const cluster = require('cluster');const http = require('http');const numCPUs = require('os').cpus().length;
if (cluster.isMaster) { console.