Signatur
Beschreibung
Swoole\Lock ist eine Klasse aus dem Swoole-Framework, die verschiedene Arten von Sperren für die Synchronisation zwischen mehreren Prozessen oder Coroutines bereitstellt. Sie unterstützt unter anderem Mutex-Locks, Read-Write-Locks, Spinlocks und Semaphoren. Dies ist besonders nützlich, wenn mehrere Worker-Prozesse auf gemeinsam genutzte Ressourcen (z. B. Shared Memory) zugreifen müssen.
Die Klasse kapselt die POSIX-Synchronisationsprimitive und macht sie in PHP einfach nutzbar. Der Typ der Sperre wird beim Instanziieren über eine Konstante festgelegt, z. B. SWOOLE_MUTEX, SWOOLE_RWLOCK, SWOOLE_SEM oder SWOOLE_SPINLOCK.
Typische Anwendungsfälle sind der Schutz kritischer Abschnitte in Multi-Process-Servern, bei denen z. B. ein Zähler in gemeinsamem Speicher atomar inkrementiert werden soll, oder die Koordination von Lese- und Schreibzugriffen auf eine gemeinsame Datenstruktur.
Achtung: Swoole\Lock ist nicht für den Einsatz innerhalb von Coroutines innerhalb desselben Prozesses konzipiert; dort sollte stattdessen Swoole\Coroutine\Lock verwendet werden, da das Blockieren des Event-Loops zu Deadlocks führen kann.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type | int | SWOOLE_MUTEX | Typ der Sperre. Mögliche Werte: SWOOLE_MUTEX (Standard), SWOOLE_RWLOCK, SWOOLE_SEM, SWOOLE_SPINLOCK, SWOOLE_FILELOCK. |
| $filename | string | Nur bei SWOOLE_FILELOCK erforderlich: Der Dateipfad, der als Basis für die Dateisperre verwendet wird. |
Rückgabewert
Beispiele
Einfacher Mutex-Lock zwischen Worker-Prozessen
<?php
// Mutex-Lock erstellen (im Elternprozess, bevor fork() aufgerufen wird)
$lock = new Swoole\Lock(SWOOLE_MUTEX);
$pid = pcntl_fork();
if ($pid === 0) {
// Kindprozess
echo "Kind: Warte auf Lock...\n";
$lock->lock();
echo "Kind: Lock erhalten, arbeite 1 Sekunde...\n";
sleep(1);
$lock->unlock();
echo "Kind: Lock freigegeben.\n";
exit(0);
} else {
// Elternprozess
echo "Eltern: Warte auf Lock...\n";
$lock->lock();
echo "Eltern: Lock erhalten, arbeite 1 Sekunde...\n";
sleep(1);
$lock->unlock();
echo "Eltern: Lock freigegeben.\n";
pcntl_wait($status);
}
Read-Write-Lock für parallele Lesezugriffe
<?php
// RWLOCK: Mehrere Leser gleichzeitig, aber nur ein Schreiber
$lock = new Swoole\Lock(SWOOLE_RWLOCK);
$pid = pcntl_fork();
if ($pid === 0) {
// Kindprozess: Leser
$lock->lock_read();
echo "Kind liest Daten (Read-Lock aktiv)...\n";
sleep(1);
$lock->unlock();
echo "Kind: Read-Lock freigegeben.\n";
exit(0);
} else {
// Elternprozess: Schreiber wartet, bis kein Leser mehr aktiv ist
sleep(0); // Sicherstellen, dass der Kindprozess zuerst locked
$lock->lock();
echo "Eltern schreibt Daten (Write-Lock aktiv)...\n";
$lock->unlock();
echo "Eltern: Write-Lock freigegeben.\n";
pcntl_wait($status);
}
Nicht-blockierendes Sperren mit trylock()
<?php
$lock = new Swoole\Lock(SWOOLE_MUTEX);
// Versuche Lock zu erhalten, ohne zu blockieren
if ($lock->trylock()) {
echo "Lock erfolgreich erhalten, kritischen Abschnitt ausführen...\n";
// ... Arbeit erledigen ...
$lock->unlock();
echo "Lock freigegeben.\n";
} else {
echo "Lock nicht verfügbar, überspringe kritischen Abschnitt.\n";
}
// Wichtig · Fallstricke
Deadlock-Gefahr: Das Aufrufen von lock() innerhalb einer Swoole-Coroutine im selben Prozess blockiert den gesamten Event-Loop und führt zu einem Deadlock. Für Coroutines sollte Swoole\Coroutine\Lock genutzt werden.
Ressourcen freigeben: Locks müssen korrekt mit unlock() freigegeben werden. Ein nicht freigegebener Lock führt dazu, dass andere Prozesse unbegrenzt warten. Nutze try/finally-Blöcke, um die Freigabe auch im Fehlerfall sicherzustellen.
Plattformabhängigkeit: SWOOLE_FILELOCK und SWOOLE_SEM sind möglicherweise nicht auf allen Betriebssystemen verfügbar. Swoole läuft primär unter Linux; unter macOS gibt es Einschränkungen bei bestimmten Lock-Typen.
Initialisierung vor fork(): Der Lock muss im Elternprozess erstellt werden, bevor Worker-Prozesse mit fork() oder Swooles Prozessmanagement gestartet werden, damit er im gemeinsamen Speicher liegt.