Einleitung: Warum PHP Nebenläufigkeit braucht
PHP gilt traditionell als synchrone Sprache, bei der jede Anfrage sequenziell verarbeitet wird. Moderne Webanwendungen erfordern jedoch die gleichzeitige Ausführung vieler Aufgaben: Warteschlangenverarbeitung, API-Interaktion, Bildverarbeitung, Daten-Parsing. Nebenläufigkeit und Multithreading in PHP ermöglichen die Lösung dieser Probleme und steigern die Leistung und Reaktionsfähigkeit von Anwendungen.
In diesem Artikel betrachten wir die wichtigsten Ansätze: Multithreading mit pthreads, parallele Prozesse mit pcntl_fork, asynchrone Programmierung mit ReactPHP und moderne Fibers in PHP 8.1+. Jede Methode hat ihre Stärken und Einschränkungen, die wir anhand praktischer Beispiele untersuchen werden.
Ansatz 1: Multithreading mit der pthreads-Erweiterung
pthreads ist eine Erweiterung für die Arbeit mit Threads in PHP. Sie ist nur für die CLI-Version verfügbar und erfordert eine Kompilierung mit dem Flag --enable-maintainer-zts. Threads teilen sich den Speicher, was einen effizienten Datenaustausch ermöglicht, aber Vorsicht bei Sperren (Locks) erfordert.
Installation und Konfiguration
# Installation über peclpecl install pthreads
# Überprüfung in der php.iniextension=pthreads.soBeispiel: Parallele Verarbeitung eines Arrays
<?phpclass WorkerThread extends Thread { private $data; private $result;
public function __construct($data) { $this->data = $data; }
public function run() { // Simulation einer schweren Operation $this->result = array_map(function($item) { sleep(1); // 1 Sekunde pro Element return $item * 2; }, $this->data); }
public function getResult() { return $this->result; }}
// 5 Threads erstellen$threads = [];$dataChunks = array_chunk(range(1, 100), 20);
foreach ($dataChunks as $chunk) { $thread = new WorkerThread($chunk); $thread->start(); $threads[] = $thread;}
// Ergebnisse sammeln$finalResult = [];foreach ($threads as $thread) { $thread->join(); $finalResult = array_merge($finalResult, $thread->getResult());}
echo "Verarbeitet " . count($finalResult) . " Elemente in ~5 Sekunden statt 100.";Wichtig: pthreads funktioniert nicht in einer Webserver-Umgebung (Apache/Nginx + mod_php). Verwenden Sie es nur für CLI-Skripte, Worker und Dienste (Daemons).
Ansatz 2: Parallele Prozesse mit pcntl_fork
Die Funktion pcntl_fork() erstellt einen untergeordneten Prozess, indem sie das aktuelle Skript kopiert. Prozesse sind speicherseitig isoliert, was sicherer als Threads ist, aber die Interprozesskommunikation (IPC) erfordert zusätzliche Mechanismen: Message Queues, Shared Memory oder Sockets.
Beispiel: Paralleles Laden von URLs
<?php$urls = [ 'https://api.example.com/data1', 'https://api.example.com/data2', 'https://api.example.com/data3',];
$pids = [];foreach ($urls as $url) { $pid = pcntl_fork(); if ($pid == -1) { die("Fehler bei fork"); } elseif ($pid == 0) { // Untergeordneter Prozess $content = file_get_contents($url); file_put_contents('/tmp/' . md5($url) . '.json', $content); exit(0); // Wichtig: untergeordneten Prozess beenden } else { $pids[] = $pid; }}
// Warten auf die Beendigung aller untergeordneten Prozesseforeach ($pids as $pid) { pcntl_waitpid($pid, $status);}
echo "Alle URLs wurden parallel geladen.";Einschränkungen:
- Funktioniert nicht mit einem Webserver (nur CLI).
- Jeder Prozess verbraucht den Speicher des Elternprozesses.
- Der Zugriff auf gemeinsame Ressourcen ist schwer zu synchronisieren.
Ansatz 3: Asynchronität mit ReactPHP
ReactPHP ist eine Bibliothek für ereignisgesteuerte Programmi