Concorrência e Multithreading em JavaScript: Nível Avançado

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Concorrência e Multithreading em JavaScript: Nível Avançado

\n\n

JavaScript é tradicionalmente considerado uma linguagem single-thread, mas o ecossistema moderno do Node.js oferece ferramentas poderosas para trabalhar com concorrência e verdadeiro multithreading. Neste artigo, abordaremos técnicas avançadas: desde os detalhes do Event Loop até o uso de Worker Threads, SharedArrayBuffer e Atomics. Você aprenderá a distribuir carga de forma eficiente, evitar condições de corrida e construir aplicações escaláveis.

\n\n

1. Event Loop, Microtasks e Macrotasks: O Fundamento da Concorrência

\n\n

Entender o Event Loop é a chave para gerenciar a concorrência sem bloqueios. No Node.js, o ciclo de eventos consiste em várias fases: timers, callbacks de I/O, idle, poll, check (setImmediate) e close. É importante distinguir entre microtasks (Promise, process.nextTick) e macrotasks (setTimeout, setInterval, I/O).

\n\n

Microtasks são executadas imediatamente após o término da fase atual, antes da próxima macrotask. Isso pode levar à "fome" do Event Loop se microtasks forem geradas infinitamente.

\n\n
// Exemplo: microtasks bloqueiam macrotasks\nsetTimeout(() => console.log('Macrotask'), 0);\n\nPromise.resolve().then(() => {\n  // Microtask infinita\n  process.nextTick(() => {\n    console.log('Microtask');\n    // Chamada recursiva bloqueará o Event Loop\n    process.nextTick(() => process.nextTick(() => {}));\n  });\n});\n// Saída: 'Microtask' (infinitamente), 'Macrotask' nunca será executada
\n\n

Para controle avançado, use queueMicrotask() e setImmediate(). Lembre-se: process.nextTick tem prioridade sobre as microtasks de Promise.

\n\n

2. Worker Threads: Multithreading Real no Node.js

\n\n

O módulo worker_threads permite executar JavaScript em threads paralelas. Cada Worker tem sua própria instância V8 e memória isolada. A troca de dados ocorre por meio de mensagens ou SharedArrayBuffer.

\n\n

Criando um Worker simples:

\n\n
// main.js\nconst { Worker } = require('worker_threads');\n\nfunction runWorker(file, data) {\n  return new Promise((resolve, reject) => {\n    const worker = new Worker(file, { workerData: data });\n    worker.on('message', resolve);\n    worker.on('error', reject);\n    worker.on('exit', (code) => {\n      if (code !== 0) reject(new Error(`Worker parou com código ${code}`));\n    });\n  });\n}\n\n// Execução\nrunWorker('./worker.js', { iterations: 1e9 })\n  .then(result => console.log('Resultado:', result))\n  .catch(err => console.error(err));
\n\n
// worker.js\nconst { parentPort, workerData } = require('worker_threads');\n\nfunction heavyComputation(n) {\n  let sum = 0;\n  for (let i = 0; i < n; i++) { sum += Math.sqrt(i); }\n  return sum;\n}\n\nparentPort.postMessage(heavyComputation(workerData.iterations));
\n\n

Importante: O Worker não tem acesso ao DOM, objetos globais do processo (process.env) ou módulos carregados na thread principal. Transmita apenas dados serializáveis.

\n\n

Pool de Workers

\n

Criar um Worker para cada tarefa é custoso. Use um pool:

\n\n
class WorkerPool {\n  constructor(file, size = 4) {\n    this.workers = [];\n    this.queue = [];\n    for (let i = 0; i < size; i++) {\n      const worker = new Worker(file);\n      worker.on('message', (result) => this._handleResult(worker, result));\n      worker.on('error', (err) => this._handleError(worker, err));\n      this.workers.push(worker);\n    }\n  }\n\n  runTask(data) {\n    return new Promise((resolve, reject) => {\n      this.queue.push({ data, resolve, reject });\n      this._processQueue();\n    });\n  }\n\n  _processQueue() {\n    if (this.queue.length === 0) return;\n    const worker = this.workers.find(w => !w.busy);\n    if (!worker) return;\n    worker.busy = true;\n    const task = this.queue.shift();                

Blogs

Book Recommendations