El modelo de concurrencia de PHP
Comprenda la E/S bloqueante y cuándo resulta útil la asincronía.
El modelo de concurrencia de PHP es una lección gratuita de PHP Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de PHP Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de PHP Academy incluye 4 lecciones en total.
PHP es síncrono de forma predeterminada
El PHP clásico ejecuta una solicitud por proceso, de principio a fin, con E/S bloqueante. Una llamada a file_get_contents() que accede a una API lenta bloquea todo el script hasta que llegan los bytes. El modelo sin estado compartido (un proceso nuevo por solicitud, cuyo estado se destruye al final) es maravillosamente sencillo, pero significa que un único trabajador solo puede hacer una cosa a la vez. Esta lección muestra dónde resulta problemático y dónde ayuda la asincronía.
E/S bloqueante, cuantificada
Observe cómo el tiempo transcurrido está dominado por la espera, no por el cálculo. Tres solicitudes secuenciales de 1 segundo tardan aproximadamente 3 segundos, aunque la CPU permanece inactiva todo el tiempo.
<?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.00sTrabajo limitado por CPU frente a trabajo limitado por E/S
La concurrencia solo ayuda con el trabajo limitado por E/S: el tiempo dedicado a esperar a la red, el disco o la base de datos. Para el trabajo limitado por CPU (hashing, redimensionado de imágenes y análisis sintáctico), un solo hilo ya está saturado; async solo añade sobrecarga de planificación. Diagnostique primero:
- Muchas llamadas HTTP o consultas a la base de datos lentas → async ofrece grandes beneficios.
- Bucles numéricos intensivos → use paralelismo (procesos o hilos), no un bucle de eventos.
Cómo ha escalado PHP hasta ahora
Históricamente, PHP ha escalado mediante la concurrencia a nivel de proceso: PHP-FPM mantiene un grupo de procesos trabajadores; cada uno gestiona una solicitud a la vez y el sistema operativo los multiplexa. Esto es concurrencia real entre solicitudes, pero no ofrece nada dentro de una solicitud: con código bloqueante estándar todavía no puede distribuir 50 llamadas de API en paralelo dentro de un mismo controlador.
La idea del bucle de eventos
El PHP asíncrono introduce un bucle de eventos: un único hilo que registra las operaciones de E/S como no bloqueantes y luego espera en stream_select()/epoll hasta que alguna está lista, ejecutando callbacks a medida que llegan los datos. Un solo hilo gestiona miles de sockets porque nunca permanece inactivo esperando a uno solo.
<?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, no preventivo
El PHP asíncrono es cooperativo: las tareas se ejecutan hasta que ceden voluntariamente el control en un punto de E/S. No existe apropiación preventiva, por lo que una llamada bloqueante larga o un bucle de CPU ajustado detiene todo el bucle y deja sin recursos a las demás tareas. Regla de oro: nunca llame a funciones bloqueantes (sleep, PDO bloqueante, file_get_contents) dentro de una tarea del bucle de eventos. Utilice los equivalentes asíncronos del bucle.
Tres enfoques en PHP
El PHP moderno ofrece un conjunto de herramientas por capas:
- Fibers (PHP 8.1, núcleo): una primitiva de bajo nivel para pausar y reanudar una pila de llamadas. Es el componente básico, no un framework completo.
- ReactPHP / Amp: bucles de eventos de usuario basados en streams (y actualmente también en Fibers) para realizar E/S no bloqueante sin extensiones.
- Swoole / OpenSwoole: una extensión de C que proporciona coroutines, un servidor de alto rendimiento y llamadas bloqueantes interceptadas.
Detecte qué está disponible en tiempo de ejecución antes de elegir una estrategia.
<?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;Las promesas modelan valores futuros
Antes de las Fibers, el PHP asíncrono exponía los resultados pendientes como promesas: marcadores de posición para valores que se resuelven más adelante. Puede asociar callbacks mediante then(). Funciona, pero produce cadenas anidadas; las Fibers permiten que las bibliotecas oculten esta complejidad tras un await con apariencia 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";
});Concurrencia frente a paralelismo
Sea preciso:
- Concurrencia: muchas tareas en curso, intercaladas en un solo hilo (bucle de eventos). Es ideal para la E/S.
- Paralelismo: muchas tareas ejecutándose simultáneamente en varios núcleos (procesos, la extensión
parallel, trabajadores de tareas de Swoole). Es necesario para el trabajo de CPU.
Un bucle de eventos proporciona concurrencia, no paralelismo. El fragmento siguiente muestra paralelismo a nivel de procesos con proc_open: tres trabajadores se ejecutan a la vez en procesos independientes del sistema operativo.
<?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";Cuándo NO recurrir a la asincronía
La asincronía tiene costes: un trabajador de larga duración implica que PHP ya no elimina el estado entre solicitudes, por lo que las fugas de memoria, las cachés estáticas y el estado obsoleto de las conexiones pasan a ser responsabilidad suya. Si un gestor de solicitudes realiza una consulta a la base de datos y devuelve la respuesta, PHP-FPM es más sencillo e igual de rápido. Recurra a la asincronía cuando necesite fan-out de E/S, WebSockets/long polling, streaming o un servidor persistente.
Paralelismo real: ext-parallel y procesos
Para distribuir trabajo limitado por la CPU, PHP puede ejecutar paralelismo real a nivel del sistema operativo. La extensión parallel inicia hilos de trabajo con memoria aislada; como alternativa, proc_open/pcntl_fork crean procesos. A diferencia de un bucle de eventos, estas opciones utilizan varios núcleos simultáneamente: son la herramienta adecuada cuando el cuello de botella es el cálculo y no la 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;Comprobación rápida
¿Qué ocurre si se llama a sleep(2) de forma bloqueante dentro de una tarea del bucle de eventos?
Resumen
Ahora dispone de un modelo mental de la concurrencia en PHP:
- El PHP predeterminado es síncrono, bloqueante y sin estado compartido; FPM escala entre solicitudes, no dentro de una sola.
- La asincronía ayuda con el trabajo limitado por E/S mediante un bucle de eventos de un solo hilo que utiliza streams no bloqueantes.
- El modelo es cooperativo: nunca bloquee el bucle; el trabajo prolongado de CPU necesita paralelismo, no concurrencia.
- El conjunto de herramientas de PHP: Fibers (primitiva), ReactPHP/Amp (bucles de usuario + promesas), Swoole (extensión de coroutines).
Preguntas frecuentes
¿La lección «El modelo de concurrencia de PHP» es gratis?
Sí — el texto completo de «El modelo de concurrencia de PHP» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de PHP Academy, actualiza a CoddyKit PRO. El curso de PHP Academy incluye 4 lecciones en total.
¿Qué aprenderé en «El modelo de concurrencia de PHP»?
Comprenda la E/S bloqueante y cuándo resulta útil la asincronía. Practicas PHP Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar PHP Academy?
No se requiere experiencia previa. PHP Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.
¿Cuánto tiempo toma la lección «El modelo de concurrencia de PHP»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de PHP Academy?
Sí. Cada lección de PHP Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- El modelo de concurrencia de PHP
- Fibers de PHP 8.1
- Bucles de eventos con ReactPHP
- Servidores de alto rendimiento con Swoole