Concorrência e Multithreading em PHP: Nível Avançado
O PHP é tradicionalmente associado à execução síncrona de scripts, mas as aplicações web modernas exigem o processamento de múltiplas tarefas simultaneamente. A concorrência (concurrency) e o multithreading (multithreading) permitem aumentar significativamente o desempenho, acelerar o processamento de requisições e utilizar eficientemente os recursos do servidor. Neste artigo, abordaremos técnicas avançadas de trabalho com multithreading em PHP, incluindo a extensão pthreads, processos paralelos, chamadas assíncronas e gerenciamento de threads.
1. Fundamentos do Multithreading em PHP: Extensão pthreads
A extensão pthreads é a principal ferramenta para trabalhar com threads em PHP. Ela permite criar, executar e sincronizar múltiplas threads de execução dentro de um único processo. Importante: pthreads funciona apenas no modo CLI e requer uma compilação do PHP com suporte a threads (ZTS — Zend Thread Safety).
Exemplo de criação de uma thread simples:
<?phpclass WorkerThread extends Thread { private $id; public function __construct($id) { $this->id = $id; } public function run() { echo "Thread {$this->id} iniciada"; sleep(2); echo "Thread {$this->id} finalizada"; }}
$threads = [];for ($i = 1; $i <= 5; $i++) { $threads[$i] = new WorkerThread($i); $threads[$i]->start();}
foreach ($threads as $thread) { $thread->join();}?>O método start() inicia a thread, e join() aguarda sua conclusão. Sem join(), a thread principal pode terminar antes das threads filhas.
2. Sincronização de Threads e Recursos Compartilhados
Ao trabalhar com multithreading, é crucial sincronizar o acesso a dados compartilhados. O PHP oferece vários mecanismos: objetos Mutex, Volatile e Threaded.
Mutex (exclusão mútua) — bloqueia o acesso a um recurso para outras threads enquanto uma thread trabalha com ele.
<?phpclass Counter extends Threaded { private $count = 0; public function increment() { $this->synchronized(function() { $this->count++; }); } public function getCount() { return $this->count; }}
class IncrementThread extends Thread { private $counter; public function __construct(Counter $counter) { $this->counter = $counter; } public function run() { for ($i = 0; $i < 1000; $i++) { $this->counter->increment(); } }}
$counter = new Counter();$threads = [];
for ($i = 0; $i < 10; $i++) { $threads[$i] = new IncrementThread($counter); $threads[$i]->start();}
foreach ($threads as $thread) { $thread->join();}
echo "Valor final: " . $counter->getCount(); // 10000?>Volatile — garante que as alterações em uma variável sejam visíveis para todas as threads. Use Volatile para tipos de dados simples.
$sharedFlag = new Volatile();$sharedFlag->flag = false;
// Em uma thread$sharedFlag->flag = true;
// Em outra threadif ($sharedFlag->flag) { echo "Bandeira definida";}3. Processos Paralelos e Tarefas Assíncronas
Se a extensão pthreads não estiver disponível (por exemplo, em hospedagem compartilhada), é possível usar processos paralelos via pcntl_fork() ou bibliotecas assíncronas, como ReactPHP ou Amp.
pcntl_fork() — cria um processo filho que é executado em paralelo com o processo pai.
<?php$pid = pcntl_fork();if ($pid == -1) { die("Falha ao criar processo");} elseif ($pid)