Concurrencia y multihilo en PHP: nivel avanzado

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: por qué la concurrencia en PHP no es un mito

\n

Tradicionalmente, PHP se considera un lenguaje síncrono donde cada solicitud se procesa secuencialmente. Sin embargo, las aplicaciones modernas —desde el procesamiento de video hasta el análisis de grandes datos— requieren la ejecución de múltiples tareas simultáneamente. Sin concurrencia, corre el riesgo de chocar contra el "muro de rendimiento", donde incluso un servidor potente permanece inactivo esperando que se completen las operaciones de entrada/salida.

\n

En este artículo, analizaremos técnicas avanzadas para trabajar con concurrencia en PHP: desde llamadas al sistema hasta extensiones a nivel de kernel. Aprenderá cómo hacer que PHP funcione en paralelo sin perder el control sobre los recursos.

\n\n

1. Fundamentos: procesos vs hilos en PHP

\n

Antes de sumergirnos en el código, es importante entender la diferencia entre procesos e hilos en el contexto de PHP.

\n
    \n
  • Procesos — instancias aisladas, cada una con su propia memoria. Se crean mediante pcntl_fork(). Son adecuados para tareas pesadas, pero requieren comunicación entre procesos (IPC).
  • \n
  • Hilos — "subtareas" ligeras dentro de un mismo proceso que comparten memoria. Se implementan mediante la extensión pthreads. Son ideales para trabajar con datos compartidos, pero requieren sincronización.
  • \n
\n

Para un nivel avanzado, es importante saber combinar ambos enfoques. Por ejemplo, usar forks para aislar tareas críticas y hilos para el procesamiento paralelo dentro de un mismo contexto.

\n\n

1.1 Procesos paralelos mediante pcntl_fork()

\n

La llamada al sistema pcntl_fork() crea un proceso hijo que copia la memoria del padre. Veamos un ejemplo de procesamiento paralelo de varias URL:

\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('No se pudo crear el proceso');\n    } elseif ($pid) {\n        // Proceso padre: guardamos el PID\n        $pids[] = $pid;\n    } else {\n        // Proceso hijo: realizamos la descarga\n        $data = file_get_contents($url);\n        file_put_contents('/tmp/' . md5($url) . '.json', $data);\n        exit(0); // Finalizamos el proceso hijo\n    }\n}\n\n// Esperamos a que todos los procesos terminen\nforeach ($pids as $pid) {\n    pcntl_waitpid($pid, $status);\n}\necho "¡Todas las URL se procesaron en paralelo!";\n?>
\n

Importante: después de fork(), los procesos hijos heredan todos los descriptores de archivo y conexiones a la base de datos abiertos. Ciérrelos explícitamente en el proceso hijo para evitar conflictos.

\n\n

2. Tareas asíncronas con ReactPHP y Amp

\n

Para aplicaciones web donde la reactividad es importante, utilice bibliotecas de bucle orientado a eventos. ReactPHP y Amp permiten realizar operaciones no bloqueantes sin crear procesos separados.

\n\n

2.1 Ejemplo con ReactPHP

\n

Instale la biblioteca mediante Composer: composer require react/react. A continuación, un cliente HTTP asíncrono que envía tres solicitudes simultáneamente:

\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 "Respuesta de {$url}: " . $response->getCode() . PHP_EOL;\n    });\n    $request->end();\n}\n\n$loop->run();\n?>
\n

ReactPHP crea un único bucle de eventos que procesa todas las solicitudes sin bloqueo. Esto es ideal para puertas de enlace API o microservicios donde la velocidad de respuesta es importante.

\n\n

3. Gestión de hilos con pthreads (compilación ZTS)

\n

La extensión pthreads es la única forma de obtener verdadero multihilo en PHP.

Blogs

Book Recommendations