Start · Sprachen · PHP · Referenz · sem_acquire

sem_acquire

Funktion

Fordert Zugriff auf einen System-V-Semaphor an und blockiert bei Bedarf, bis dieser verfügbar ist.

seit PHP 4.0.0 Kategorie: misc

Signatur

sem_acquire(SysvSemaphore $semaphore, bool $non_blocking = false): bool

Beschreibung

sem_acquire() wird verwendet, um exklusiven Zugriff auf eine kritische Sektion in parallelen Prozessen zu erlangen. Ist der Semaphor bereits von einem anderen Prozess belegt, blockiert die Funktion standardmäßig so lange, bis der Semaphor freigegeben wird. Dadurch lassen sich Race Conditions vermeiden, wenn mehrere PHP-Prozesse auf gemeinsame Ressourcen (z. B. Dateien, Shared Memory) zugreifen.

Mit dem optionalen Parameter non_blocking kann verhindert werden, dass der aufrufende Prozess wartet: Wenn der Semaphor belegt ist, gibt die Funktion sofort false zurück, anstatt zu blockieren. Dies ist nützlich, wenn ein Prozess bei nicht verfügbarem Semaphor alternativ handeln soll.

Ein Prozess kann denselben Semaphor mehrfach acquiren. Bei jeder erfolgreichen Anforderung muss am Ende ein entsprechendes sem_release() aufgerufen werden, da sonst andere Prozesse dauerhaft blockiert bleiben. Die maximale Anzahl gleichzeitiger Anforderungen wird beim Erstellen des Semaphors über sem_get() mit dem Parameter max_acquire festgelegt.

Semaphoren sind ein IPC-Mechanismus (Inter-Process Communication) des Betriebssystems und stehen nur unter Unix/Linux zur Verfügung. Unter Windows ist diese Funktion nicht verfügbar.

Parameter

Name Typ Default Beschreibung
$semaphore Pflicht SysvSemaphore Ein Semaphor-Handle, das zuvor mit sem_get() erstellt wurde.
$non_blocking bool false Wenn true, blockiert die Funktion nicht, sondern gibt sofort false zurück, falls der Semaphor nicht verfügbar ist. Standard ist false (blockierendes Verhalten).

Rückgabewert

Typ
bool
Beschreibung
Gibt true zurück, wenn der Semaphor erfolgreich angefordert wurde. Gibt false zurück, wenn non_blocking auf true gesetzt ist und der Semaphor gerade belegt ist, oder wenn ein Fehler aufgetreten ist.

Beispiele

Kritische Sektion mit Semaphor schützen

<?php
// Semaphor erstellen (Schlüssel, max. gleichzeitige Prozesse, Berechtigungen)
$semaphore = sem_get(ftok(__FILE__, 'a'), 1, 0666, true);

if ($semaphore === false) {
    die('Semaphor konnte nicht erstellt werden.');
}

// Semaphor anfordern (blockiert, bis er verfügbar ist)
if (sem_acquire($semaphore)) {
    echo 'Kritische Sektion betreten.' . PHP_EOL;

    // Hier: exklusiver Zugriff auf gemeinsame Ressource
    sleep(1); // Simulierte Arbeit

    echo 'Kritische Sektion verlassen.' . PHP_EOL;

    // Semaphor freigeben
    sem_release($semaphore);
} else {
    echo 'Semaphor konnte nicht angefordert werden.' . PHP_EOL;
}
?>
Kritische Sektion betreten. Kritische Sektion verlassen.

Nicht-blockierender Semaphor-Zugriff

<?php
$semaphore = sem_get(ftok(__FILE__, 'b'), 1, 0666, true);

if ($semaphore === false) {
    die('Semaphor konnte nicht erstellt werden.');
}

// Nicht-blockierend versuchen
if (sem_acquire($semaphore, true)) {
    echo 'Semaphor erhalten, führe Aufgabe aus.' . PHP_EOL;

    // Exklusive Arbeit
    sleep(1);

    sem_release($semaphore);
} else {
    echo 'Semaphor ist belegt, überspringe Aufgabe.' . PHP_EOL;
    // Alternative Behandlung, z. B. Queue-Eintrag oder Logging
}
?>
Semaphor erhalten, führe Aufgabe aus.

// Wichtig · Fallstricke

Nur unter Unix/Linux verfügbar: System-V-Semaphoren sind ein POSIX-IPC-Mechanismus und stehen unter Windows nicht zur Verfügung. Skripte, die sem_acquire() verwenden, sind daher nicht portabel.

Deadlock-Gefahr: Wenn ein Prozess den Semaphor acquirt, aber nie sem_release() aufruft (z. B. durch einen unbehandelten Fehler oder ein abruptes Prozessende), kann es zu Deadlocks kommen. Es empfiehlt sich daher, sem_release() in einem finally-Block oder über einen register_shutdown_function()-Handler aufzurufen.

Konfiguration: Die PHP-Extension sysvsem muss beim Kompilieren aktiviert sein (--enable-sysvsem). Seit PHP 8.0 liefert sem_get() ein SysvSemaphore-Objekt statt einer Ressource.