Concurrencia y multiproceso en PHP: de la teoría a la práctica

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

Concurrencia y multiproceso en PHP: enfoques modernos



PHP se asocia tradicionalmente con la ejecución síncrona de código. Sin embargo, las aplicaciones web modernas requieren procesar varias tareas simultáneamente: desde la carga de archivos hasta el análisis de grandes datos. En este artículo analizaremos cómo implementar concurrencia y multiproceso en PHP, utilizando herramientas integradas y de terceros.



¿Qué es concurrencia y multiproceso?



Concurrencia es la capacidad de un programa para ejecutar varias tareas "simultáneamente", alternando entre ellas. Multiproceso es un caso particular de concurrencia, donde las tareas se ejecutan en hilos separados del sistema operativo.



En PHP, hasta la versión 7.4 no existía soporte nativo para hilos. Sin embargo, con la aparición de las extensiones pthreads y parallel, así como la mejora en el trabajo con procesos, la situación cambió.



1. Multiproceso con la extensión parallel



La extensión parallel es una forma moderna de trabajar con hilos en PHP 7.4+. Utiliza memoria compartida, lo que permite intercambiar datos eficientemente entre hilos.



Instalación:

pecl install parallel


Ejemplo de creación de un hilo:

<?phpuse parallel\\Runtime;

$runtime = new Runtime();$future = $runtime->run(function() { // Cálculos pesados $result = 0; for ($i = 0; $i < 1000000; $i++) { $result += sqrt($i); } return $result;});

echo "El hilo principal continúa trabajando...";$result = $future->value(); // Obtenemos el resultadoecho "Resultado: $result";?>


Ventajas de parallel:

  • Soporte nativo de hilos sin dependencias adicionales
  • Memoria compartida entre hilos
  • Posibilidad de pasar closures y objetos


Desventajas:

  • Requiere PHP 7.4+ y ZTS (Zend Thread Safety)
  • No compatible con Windows
  • Dificultades con la depuración


2. Asincronía mediante procesos: pcntl_fork



Si no necesita memoria compartida, puede usar procesos con pcntl_fork(). Este es el enfoque clásico de Unix.



<?php$pid = pcntl_fork();

if ($pid == -1) { die("Error al crear el proceso");} elseif ($pid) { // Proceso padre echo "Padre: esperando al proceso hijo..."; pcntl_wait($status); echo "Padre: proceso hijo finalizado";} else { // Proceso hijo echo "Hijo: ejecutando tarea..."; sleep(3); exit(0);}?>


Características del trabajo con procesos:

  • Cada proceso tiene su propia memoria
  • Para intercambiar datos use sockets, memoria compartida (shmop) o archivos
  • Es necesario manejar procesos zombie mediante pcntl_wait()


3. Concurrencia mediante funciones asíncronas y ReactPHP



Para tareas de entrada/salida (solicitudes de red, lectura de archivos) es más eficiente usar bibliotecas asíncronas como ReactPHP o Amp. No crean hilos, pero permiten ejecutar tareas concurrentemente mediante un event loop.



Ejemplo con ReactPHP:

<?phprequire 'vendor/autoload.php';

use React\\EventLoop\\Factory;use React\\Http\\Browser;

$loop = Factory::create();$client = new Browser($loop);

$promises = [];$urls = [ 'https://api.example.com/data1', 'https://api.example.com/data2', 'https://api.example.com/data3'];

foreach ($urls as $url) { $promises[] = $client->get($url);}

// Esperamos todas las solicitudes en paralelo$results = [];foreach ($promises as $promise) { $results[] = $promise->wait();}

$loop->run();print_r($results);?>

Blogs

Book Recommendations