Start · Sprachen · PHP · Referenz · Swoole\Lock

Swoole\Lock

Klasse

Bietet prozessübergreifende Sperrmechanismen (Mutexe, Lese-/Schreibsperren, Semaphoren) für die parallele Programmierung mit Swoole.

seit PHP 1.0.0 Kategorie: misc

Signatur

class Swoole\Lock

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

Typ

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);
}
Eltern: Warte auf Lock... Eltern: Lock erhalten, arbeite 1 Sekunde... Kind: Warte auf Lock... Eltern: Lock freigegeben. Kind: Lock erhalten, arbeite 1 Sekunde... Kind: Lock freigegeben.

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);
}
Kind liest Daten (Read-Lock aktiv)... Kind: Read-Lock freigegeben. Eltern schreibt Daten (Write-Lock aktiv)... Eltern: Write-Lock freigegeben.

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";
}
Lock erfolgreich erhalten, kritischen Abschnitt ausführen... Lock freigegeben.

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