Parallelität und Multithreading in PHP: Ein praktischer Leitfaden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

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.so

Beispiel: 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

Blogs

Buchempfehlungen