Concorrência e Multithreading em PHP: 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

Introdução: por que concorrência em PHP não é um mito

\n

Tradicionalmente, o PHP é considerado uma linguagem síncrona, onde cada requisição é processada sequencialmente. No entanto, aplicações modernas — desde processamento de vídeo até análise de grandes dados — exigem a execução de várias tarefas simultaneamente. Sem concorrência, você corre o risco de esbarrar no "muro do desempenho", onde mesmo um servidor potente fica ocioso, esperando a conclusão de operações de entrada/saída.

\n

Neste artigo, exploraremos técnicas avançadas de trabalho com concorrência em PHP: desde chamadas de sistema até extensões de nível de kernel. Você aprenderá como fazer o PHP trabalhar em paralelo sem perder o controle sobre os recursos.

\n\n

1. Fundamentos: processos vs threads em PHP

\n

Antes de mergulhar no código, é importante entender a diferença entre processos e threads no contexto do PHP.

\n
    \n
  • Processos — instâncias isoladas, cada uma com sua própria memória. Criados via pcntl_fork(). Adequados para tarefas pesadas, mas exigem comunicação entre processos (IPC).
  • \n
  • Threads — "subtarefas" leves dentro de um único processo, compartilhando memória. Implementadas através da extensão pthreads. Ideais para trabalhar com dados compartilhados, mas exigem sincronização.
  • \n
\n

Para um nível avançado, é importante saber combinar ambas as abordagens. Por exemplo, usar forks para isolar tarefas críticas e threads para processamento paralelo dentro de um mesmo contexto.

\n\n

1.1 Processos paralelos com pcntl_fork()

\n

A chamada de sistema pcntl_fork() cria um processo filho que copia a memória do pai. Veja um exemplo de processamento paralelo de várias URLs:

\n
<?php\n$urls = ['https://api.example.com/data1', 'https://api.example.com/data2', 'https://api.example.com/data3'];\n$pids = [];\n\nforeach ($urls as $url) {\n    $pid = pcntl_fork();\n    if ($pid == -1) {\n        die('Falha ao criar processo');\n    } elseif ($pid) {\n        // Processo pai: salva o PID\n        $pids[] = $pid;\n    } else {\n        // Processo filho: executa o download\n        $data = file_get_contents($url);\n        file_put_contents('/tmp/' . md5($url) . '.json', $data);\n        exit(0); // Finaliza o processo filho\n    }\n}\n\n// Aguarda a conclusão de todos os processos\nforeach ($pids as $pid) {\n    pcntl_waitpid($pid, $status);\n}\necho "Todas as URLs processadas em paralelo!";\n?>
\n

Importante: após fork(), os processos filhos herdam todos os descritores de arquivo e conexões de banco de dados abertos. Feche-os explicitamente no processo filho para evitar conflitos.

\n\n

2. Tarefas assíncronas com ReactPHP e Amp

\n

Para aplicações web onde a reatividade é importante, use bibliotecas de loop de eventos orientado a eventos. ReactPHP e Amp permitem executar operações não bloqueantes sem criar processos separados.

\n\n

2.1 Exemplo com ReactPHP

\n

Instale a biblioteca via Composer: composer require react/react. Abaixo, um cliente HTTP assíncrono que envia três requisições simultaneamente:

\n
<?php\nrequire 'vendor/autoload.php';\n\nuse React\\EventLoop\\Factory;\nuse React\\HttpClient\\Client;\n\n$loop = Factory::create();\n$client = new Client($loop);\n\n$urls = ['http://example.com', 'http://example.org', 'http://example.net'];\n$promises = [];\n\nforeach ($urls as $url) {\n    $request = $client->request('GET', $url);\n    $request->on('response', function ($response) use ($url) {\n        echo "Resposta de {$url}: " . $response->getCode() . PHP_EOL;\n    });\n    $request->end();\n}\n\n$loop->run();\n?>
\n

O ReactPHP cria um único loop de eventos que processa todas as requisições sem bloqueio. Isso é ideal para gateways de API ou microsserviços onde a velocidade de resposta é crucial.

\n\n

3. Gerenciamento de threads com pthreads (build ZTS)

\n

A extensão pthreads é a única maneira de obter multithreading real em PHP.

Blogs

Book Recommendations