Parallelität und Multithreading in PHP: Fortgeschrittenes Niveau
PHP wird traditionell mit der synchronen Ausführung von Skripten assoziiert, aber moderne Webanwendungen erfordern die gleichzeitige Verarbeitung vieler Aufgaben. Parallelität (Concurrency) und Multithreading ermöglichen es, die Leistung erheblich zu steigern, die Anfrageverarbeitung zu beschleunigen und Serverressourcen effizient zu nutzen. In diesem Artikel betrachten wir fortgeschrittene Techniken zur Arbeit mit Multithreading in PHP, einschließlich der Erweiterung pthreads, paralleler Prozesse, asynchroner Aufrufe und Thread-Verwaltung.
1. Grundlagen des Multithreadings in PHP: Die Erweiterung pthreads
Die Erweiterung pthreads ist das wichtigste Werkzeug für die Arbeit mit Threads in PHP. Sie ermöglicht es, mehrere Ausführungsthreads innerhalb eines Prozesses zu erstellen, zu starten und zu synchronisieren. Wichtig: pthreads funktioniert nur im CLI-Modus und erfordert eine PHP-Kompilierung mit Thread-Unterstützung (ZTS – Zend Thread Safety).
Beispiel für die Erstellung eines einfachen Threads:
<?phpclass WorkerThread extends Thread { private $id; public function __construct($id) { $this->id = $id; } public function run() { echo "Thread {$this->id} gestartet"; sleep(2); echo "Thread {$this->id} beendet"; }}
$threads = [];for ($i = 1; $i <= 5; $i++) { $threads[$i] = new WorkerThread($i); $threads[$i]->start();}
foreach ($threads as $thread) { $thread->join();}?>Die Methode start() startet den Thread, und join() wartet auf dessen Beendigung. Ohne join() könnte der Hauptthread vor den untergeordneten Threads beendet werden.
2. Thread-Synchronisation und gemeinsame Ressourcen
Bei der Arbeit mit Multithreading ist es entscheidend, den Zugriff auf gemeinsame Daten zu synchronisieren. PHP bietet mehrere Mechanismen: Mutex, Volatile und Threaded-Objekte.
Mutex (gegenseitiger Ausschluss) – sperrt den Zugriff auf eine Ressource für andere Threads, während ein Thread damit arbeitet.
<?phpclass Counter extends Threaded { private $count = 0; public function increment() { $this->synchronized(function() { $this->count++; }); } public function getCount() { return $this->count; }}
class IncrementThread extends Thread { private $counter; public function __construct(Counter $counter) { $this->counter = $counter; } public function run() { for ($i = 0; $i < 1000; $i++) { $this->counter->increment(); } }}
$counter = new Counter();$threads = [];
for ($i = 0; $i < 10; $i++) { $threads[$i] = new IncrementThread($counter); $threads[$i]->start();}
foreach ($threads as $thread) { $thread->join();}
echo "Endwert: " . $counter->getCount(); // 10000?>Volatile – stellt sicher, dass Änderungen an einer Variable für alle Threads sichtbar sind. Verwenden Sie Volatile für einfache Datentypen.
$sharedFlag = new Volatile();$sharedFlag->flag = false;
// In einem Thread$sharedFlag->flag = true;
// In einem anderen Threadif ($sharedFlag->flag) { echo "Flag gesetzt";}3. Parallele Prozesse und asynchrone Aufgaben
Wenn die Erweiterung pthreads nicht verfügbar ist (z. B. auf Shared Hosting), können Sie parallele Prozesse über pcntl_fork() oder asynchrone Bibliotheken wie ReactPHP oder Amp verwenden.
pcntl_fork() – erstellt einen untergeordneten Prozess, der parallel zum übergeordneten Prozess ausgeführt wird.
<?php$pid = pcntl_fork();if ($pid == -1) { die("Prozess konnte nicht erstellt werden");} elseif ($pid)