0Pricing
PHP Academy · Aula

O modelo de concorrência do PHP

Entenda a E/S bloqueante e quando a programação assíncrona ajuda.

O modelo de concorrência do PHP é uma aula grátis de PHP Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de PHP Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de PHP Academy inclui 4 aulas no total.

PHP é síncrono por padrão

O PHP clássico executa uma requisição por processo, de cima para baixo, com E/S bloqueante. Uma chamada a file_get_contents() para uma API lenta congela o script inteiro até que os bytes cheguem. O modelo de recursos não compartilhados (um processo novo por requisição, com o estado destruído ao final) é maravilhosamente simples — mas isso significa que um único processo de trabalho só pode fazer uma coisa por vez. Esta lição mostra onde isso causa problemas e onde o processamento assíncrono ajuda.

E/S bloqueante, medida

Observe o tempo decorrido, dominado pela espera e não pelo processamento. Três requisições sequenciais de 1 segundo levam aproximadamente 3 segundos, embora a CPU permaneça ociosa durante todo o tempo.

<?php
$start = microtime(true);
foreach (['a', 'b', 'c'] as $job) {
    usleep(1_000_000); // simulate a 1s blocking network call
    echo "done $job\n";
}
printf("elapsed: %.2fs\n", microtime(true) - $start); // ~3.00s

Limitado pela CPU versus limitado por E/S

A concorrência só ajuda em trabalhos limitados por E/S — tempo gasto esperando pela rede, pelo disco ou pelo banco de dados. Para trabalhos limitados pela CPU (geração de hashes, redimensionamento de imagens, análise sintática), uma única linha de execução já está saturada; o processamento assíncrono apenas acrescenta sobrecarga de agendamento. Faça o diagnóstico primeiro:

  • Muitas chamadas HTTP lentas / consultas ao banco de dados → o processamento assíncrono traz grandes ganhos.
  • Laços numéricos intensivos → use paralelismo (processos/linhas de execução), não um loop de eventos.

Como o PHP escalou até agora

Historicamente, o PHP escalou por meio da concorrência no nível de processos: o PHP-FPM mantém um conjunto de processos de trabalho; cada um trata uma requisição por vez, e o sistema operacional os multiplexa. Isso é concorrência real entre requisições, mas não oferece nada dentro de uma requisição — com código bloqueante padrão, ainda não é possível distribuir 50 chamadas de API em paralelo dentro de um único manipulador.

A ideia do loop de eventos

O PHP assíncrono introduz um loop de eventos: uma única linha de execução que registra operações de E/S como não bloqueantes e, em seguida, dorme em stream_select()/epoll até que alguma esteja pronta, acionando funções de retorno à medida que os dados chegam. Uma única linha de execução gerencia milhares de soquetes porque nunca fica ociosa esperando por apenas um deles.

<?php
// Conceptual loop: poll many non-blocking streams at once
$streams = openManyNonBlockingSockets();
while ($streams) {
    $read = $streams; $write = $except = [];
    stream_select($read, $write, $except, null); // sleeps until ANY is ready
    foreach ($read as $s) {
        handleReadyStream($s); // runs only the sockets that have data now
    }
}

Cooperativo, não preemptivo

O PHP assíncrono é cooperativo: as tarefas são executadas até cederem voluntariamente o controle em um ponto de E/S. Não há preempção, portanto uma chamada longa e bloqueante ou um laço intenso de CPU interrompe todo o loop — todas as outras tarefas ficam sem tempo de execução. Regra de ouro: nunca chame funções bloqueantes (sleep, PDO bloqueante, file_get_contents) dentro de uma tarefa do loop de eventos. Use os equivalentes assíncronos do loop.

Três abordagens em PHP

O PHP moderno oferece um conjunto de ferramentas em camadas:

  • Fibras (PHP 8.1, núcleo) — uma primitiva de baixo nível para pausar e retomar uma pilha de chamadas. É o bloco fundamental, não um framework completo.
  • ReactPHP / Amp — loops de eventos no espaço do usuário, baseados em fluxos (e agora em fibras), para E/S não bloqueante sem extensões.
  • Swoole / OpenSwoole — uma extensão em C que fornece corrotinas, um servidor de alto desempenho e chamadas bloqueantes interceptadas.

Detecte o que está disponível em tempo de execução antes de escolher uma estratégia.

<?php
echo 'Fibers: ' . (class_exists('Fiber') ? 'yes' : 'no'), PHP_EOL;
echo 'Swoole ext: ' . (extension_loaded('swoole') ? 'yes' : 'no'), PHP_EOL;
echo 'parallel ext: ' . (extension_loaded('parallel') ? 'yes' : 'no'), PHP_EOL;
echo 'PHP ' . PHP_VERSION, PHP_EOL;

As promessas representam valores futuros

Antes das fibras, o PHP assíncrono expunha resultados pendentes como promessas: um espaço reservado para um valor que é resolvido mais tarde. É possível associar funções de retorno usando then(). Isso funciona, mas leva a cadeias aninhadas; as fibras permitem que as bibliotecas ocultem esse mecanismo por trás de um await com aparência síncrona.

<?php
use React\Promise\Promise;

$promise = new Promise(function ($resolve) {
    // resolved later when I/O completes
    $resolve(42);
});
$promise->then(function ($value) {
    echo "got $value\n";
});

Concorrência versus paralelismo

Seja preciso:

  • Concorrência — muitas tarefas em andamento, intercaladas em uma única linha de execução (loop de eventos). Excelente para E/S.
  • Paralelismo — muitas tarefas executadas simultaneamente em vários núcleos (processos, a extensão parallel, trabalhadores de tarefas do Swoole). Necessário para trabalho de CPU.

Um loop de eventos oferece concorrência, não paralelismo. O trecho abaixo mostra paralelismo no nível de processos com proc_open — três trabalhadores são executados ao mesmo tempo em processos separados do OS.

<?php
$procs = [];
foreach (range(1, 3) as $i) {
    // Each worker is a separate OS process -> real parallelism
    $procs[] = proc_open(
        "php -r 'usleep(500000); echo \"worker $i done\\n\";'",
        [1 => ['pipe', 'w']], $pipes
    );
}
foreach ($procs as $p) { proc_close($p); }
echo "all workers launched in parallel\n";

Quando NOT recorrer ao assíncrono

O processamento assíncrono tem custos: um processo de trabalho de longa duração significa que o PHP deixa de limpar o estado entre requisições, portanto vazamentos de memória, caches estáticos e conexões obsoletas passam a ser sua responsabilidade. Se um manipulador de requisições faz uma consulta ao banco de dados e retorna, o PHP-FPM é mais simples e igualmente rápido. Recorra ao processamento assíncrono quando precisar de distribuição de E/S, WebSockets/consulta longa, transmissão contínua ou de um servidor persistente.

Paralelismo real: ext-parallel e processos

Para distribuir trabalho limitado pela CPU, o PHP pode executar paralelismo real no nível do OS. A extensão parallel cria linhas de execução de trabalho com memória isolada; como alternativa, proc_open/pcntl_fork criam processos. Diferentemente de um loop de eventos, essas opções usam vários núcleos simultaneamente — a ferramenta certa quando o gargalo é a computação, não a espera.

<?php
// Requires ext-parallel — runs tasks on separate threads/cores
use parallel\Runtime;

$runtime = new Runtime();
$future = $runtime->run(function (): int {
    $sum = 0;
    for ($i = 0; $i < 1_000_000; $i++) $sum += $i; // CPU work on another core
    return $sum;
});
echo $future->value(), PHP_EOL;

Verificação rápida

O que acontece quando se chama sleep(2) dentro de uma tarefa do loop de eventos?

Recapitulação

Agora você tem um modelo mental da concorrência em PHP:

  • O PHP padrão é síncrono, bloqueante e sem estado compartilhado; o FPM escala entre requisições, não dentro de uma única requisição.
  • O processamento assíncrono ajuda no trabalho limitado pela E/S por meio de um loop de eventos de uma única linha de execução, usando fluxos não bloqueantes.
  • O modelo é cooperativo — nunca bloqueie o loop; trabalhos longos de CPU precisam de paralelismo, não de concorrência.
  • O conjunto de ferramentas do PHP: fibras (primitiva), ReactPHP/Amp (loops no espaço do usuário + promessas), Swoole (extensão de corrotinas).

Perguntas Frequentes

A aula “O modelo de concorrência do PHP” é grátis?

Sim — o texto completo de “O modelo de concorrência do PHP” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de PHP Academy, atualize para CoddyKit PRO. O curso de PHP Academy inclui 4 aulas no total.

O que vou aprender em “O modelo de concorrência do PHP”?

Entenda a E/S bloqueante e quando a programação assíncrona ajuda. Você pratica PHP Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar PHP Academy?

Nenhuma experiência prévia é necessária. PHP Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.

Quanto tempo leva a aula “O modelo de concorrência do PHP”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de PHP Academy?

Sim. Cada aula de PHP Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. O modelo de concorrência do PHP
  2. Fibers do PHP 8.1
  3. Loops de eventos com ReactPHP
  4. Servidores de alto desempenho com Swoole
← Voltar para PHP Academy