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.soExemplo: 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