Concorrência e Multithreading em PHP: Guia Prático

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

Introdução: por que o PHP precisa de concorrência

O PHP é tradicionalmente considerado uma linguagem síncrona, onde cada requisição é processada sequencialmente. No entanto, aplicações web modernas exigem a execução de múltiplas tarefas simultaneamente: processamento de filas, trabalho com APIs, processamento de imagens, parsing de dados. Concorrência e multithreading em PHP permitem resolver essas tarefas, aumentando a performance e a capacidade de resposta das aplicações.

Neste artigo, vamos analisar as principais abordagens: multithreading com pthreads, processos paralelos com pcntl_fork, programação assíncrona com ReactPHP e os modernos Fibers no PHP 8.1+. Cada método tem seus pontos fortes e limitações, que veremos em exemplos práticos.



Abordagem 1: Multithreading com a extensão pthreads

pthreads é uma extensão para trabalhar com threads em PHP. Ela está disponível apenas para a versão CLI e requer compilação com a flag --enable-maintainer-zts. As threads compartilham memória, o que permite a troca eficiente de dados, mas exige cuidado com locks.

Instalação e configuração

# Instalação via peclpecl install pthreads

# Verificação no php.iniextension=pthreads.so

Exemplo: processamento paralelo de um array

<?phpclass WorkerThread extends Thread {    private $data;    private $result;

public function __construct($data) { $this->data = $data; }

public function run() { // Simulação de operação pesada $this->result = array_map(function($item) { sleep(1); // 1 segundo por elemento return $item * 2; }, $this->data); }

public function getResult() { return $this->result; }}

// Criando 5 threads$threads = [];$dataChunks = array_chunk(range(1, 100), 20);

foreach ($dataChunks as $chunk) { $thread = new WorkerThread($chunk); $thread->start(); $threads[] = $thread;}

// Coleta dos resultados$finalResult = [];foreach ($threads as $thread) { $thread->join(); $finalResult = array_merge($finalResult, $thread->getResult());}

echo "Processados " . count($finalResult) . " elementos em ~5 segundos em vez de 100.";

Importante: pthreads não funciona em ambiente web (Apache/Nginx + mod_php). Use apenas para scripts CLI, workers e daemons.



Abordagem 2: Processos paralelos com pcntl_fork

A função pcntl_fork() cria um processo filho, copiando o script atual. Os processos são isolados em memória, o que é mais seguro que threads, mas a comunicação entre processos (IPC) requer mecanismos adicionais: filas de mensagens, memória compartilhada ou sockets.

Exemplo: download paralelo de URLs

<?php$urls = [    'https://api.example.com/data1',    'https://api.example.com/data2',    'https://api.example.com/data3',];

$pids = [];foreach ($urls as $url) { $pid = pcntl_fork(); if ($pid == -1) { die("Erro no fork"); } elseif ($pid == 0) { // Processo filho $content = file_get_contents($url); file_put_contents('/tmp/' . md5($url) . '.json', $content); exit(0); // Importante finalizar o processo filho } else { $pids[] = $pid; }}

// Aguardando a finalização de todos os processos filhosforeach ($pids as $pid) { pcntl_waitpid($pid, $status);}

echo "Todas as URLs foram baixadas em paralelo.";

Limitações:

  • Não funciona com servidor web (apenas CLI).
  • Cada processo consome a memória do pai.
  • Difícil sincronizar o acesso a recursos compartilhados.


Abordagem 3: Assincronia com ReactPHP

ReactPHP é uma biblioteca para programação orientada a eventos

Blogs

Book Recommendations