Concurrence et multithreading en PHP : niveau avancé

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : pourquoi la concurrence en PHP n'est pas un mythe

\n

PHP est traditionnellement considéré comme un langage synchrone, où chaque requête est traitée séquentiellement. Cependant, les applications modernes – du traitement vidéo à l'analyse de grandes données – nécessitent l'exécution simultanée de plusieurs tâches. Sans concurrence, vous risquez de vous heurter à un "mur de performance", où même un serveur puissant reste inactif en attendant la fin des opérations d'entrée-sortie.

\n

Dans cet article, nous analyserons les techniques avancées de travail avec la concurrence en PHP : des appels système aux extensions de niveau noyau. Vous apprendrez comment faire fonctionner PHP en parallèle, sans perdre le contrôle des ressources.

\n\n

1. Bases : processus vs threads en PHP

\n

Avant de plonger dans le code, il est important de comprendre la différence entre les processus et les threads dans le contexte de PHP.

\n
    \n
  • Processus – des instances isolées, chacune avec sa propre mémoire. Créés via pcntl_fork(). Adaptés aux tâches lourdes, mais nécessitent une communication interprocessus (IPC).
  • \n
  • Threads – des "sous-tâches" légères au sein d'un même processus, partageant la mémoire. Implémentés via l'extension pthreads. Idéaux pour travailler avec des données partagées, mais nécessitent une synchronisation.
  • \n
\n

Pour un niveau avancé, il est important de savoir combiner les deux approches. Par exemple, utiliser des forks pour isoler les tâches critiques, et des threads pour le traitement parallèle au sein d'un même contexte.

\n\n

1.1 Processus parallèles via pcntl_fork()

\n

L'appel système pcntl_fork() crée un processus fils qui copie la mémoire du parent. Voici un exemple de traitement parallèle de plusieurs 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('Impossible de créer le processus');\n    } elseif ($pid) {\n        // Processus parent : on sauvegarde le PID\n        $pids[] = $pid;\n    } else {\n        // Processus fils : on exécute le téléchargement\n        $data = file_get_contents($url);\n        file_put_contents('/tmp/' . md5($url) . '.json', $data);\n        exit(0); // On termine le processus fils\n    }\n}\n\n// On attend la fin de tous les processus\nforeach ($pids as $pid) {\n    pcntl_waitpid($pid, $status);\n}\necho "Toutes les URL ont été traitées en parallèle !";\n?>
\n

Important : après fork(), les processus fils héritent de tous les descripteurs de fichiers ouverts et des connexions à la base de données. Fermez-les explicitement dans le processus fils pour éviter les conflits.

\n\n

2. Tâches asynchrones avec ReactPHP et Amp

\n

Pour les applications web où la réactivité est importante, utilisez les bibliothèques de boucle événementielle. ReactPHP et Amp permettent d'effectuer des opérations non bloquantes, sans créer de processus séparés.

\n\n

2.1 Exemple avec ReactPHP

\n

Installez la bibliothèque via Composer : composer require react/react. Ci-dessous, un client HTTP asynchrone qui envoie trois requêtes simultanément :

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

ReactPHP crée une boucle d'événements unique qui traite toutes les requêtes sans blocage. C'est idéal pour les passerelles API ou les microservices où la rapidité de réponse est importante.

\n\n

3. Gestion des threads avec pthreads (build ZTS)

\n

L'extension pthreads est le seul moyen d'obtenir un véritable multithreading en PHP.

Blogs

Book Recommendations