bg_image
header

Semaphore

Eine Semaphore ist ein Synchronisationsmechanismus, der in der Informatik und Betriebssystemtheorie verwendet wird, um den Zugriff auf gemeinsame Ressourcen in einem parallelen oder verteilten System zu steuern. Semaphoren sind besonders nützlich, um Race Conditions und Deadlocks zu vermeiden.

Typen von Semaphoren:

  1. Binäre Semaphore: Auch als "Mutex" (Mutual Exclusion) bekannt, kann nur die Werte 0 und 1 annehmen. Sie dient zur Kontrolle des Zugriffs auf eine Ressource durch genau einen Prozess oder Thread.
  2. Zählende Semaphore: Kann einen nicht-negativen ganzzahligen Wert annehmen und erlaubt den Zugriff auf eine bestimmte Anzahl gleichzeitiger Ressourcen.

Funktionsweise:

  • Wert der Semaphore: Die Semaphore hat einen Zähler, der die Anzahl der verfügbaren Ressourcen darstellt.
    • Wenn der Zähler größer als null ist, kann ein Prozess die Ressource verwenden, und der Zähler wird dekrementiert.
    • Wenn der Zähler null ist, muss der Prozess warten, bis eine Ressource freigegeben wird.

Operationen:

  • wait (P-Operation, Proberen, "to test"):
    • Überprüft, ob der Zähler größer als null ist.
    • Wenn ja, dekrementiert er den Zähler und erlaubt dem Prozess, fortzufahren.
    • Wenn nein, blockiert der Prozess, bis der Zähler größer als null wird.
  • signal (V-Operation, Verhogen, "to increment"):
    • Inkrementiert den Zähler.
    • Wenn Prozesse blockiert warten, weckt diese Operation einen der wartenden Prozesse auf, damit er die Ressource nutzen kann.

Beispiel:

Angenommen, wir haben eine Ressource, die von mehreren Threads verwendet werden kann. Eine Semaphore kann diese Ressource schützen:

// PHP-Beispiel zur Verwendung von Semaphoren (pthreads extension erforderlich)

class SemaphoreExample {
    private $semaphore;

    public function __construct($initial) {
        $this->semaphore = sem_get(ftok(__FILE__, 'a'), $initial);
    }

    public function wait() {
        sem_acquire($this->semaphore);
    }

    public function signal() {
        sem_release($this->semaphore);
    }
}

// Hauptprogramm
$sem = new SemaphoreExample(1); // Binäre Semaphore

$sem->wait();  // Kritischen Abschnitt betreten
// Zugriff auf gemeinsame Ressource
$sem->signal();  // Kritischen Abschnitt verlassen

Anwendung:

  • Zugriffssteuerung: Kontrollieren des Zugriffs auf gemeinsam genutzte Ressourcen wie Datenbanken, Dateien oder Speicherbereiche.
  • Thread-Synchronisation: Sicherstellen, dass bestimmte Abschnitte des Codes nicht gleichzeitig von mehreren Threads ausgeführt werden.
  • Erzwingen von Reihenfolgen: Koordinieren der Ausführung von Prozessen oder Threads in einer bestimmten Reihenfolge.

Semaphoren sind ein mächtiges Werkzeug, um die parallele Programmierung sicherer und kontrollierbarer zu machen, indem sie helfen, Synchronisationsprobleme zu lösen.

 

 


No Preemption

"No Preemption" (keine Unterbrechung) ist ein Konzept in der Informatik und Betriebssystemen, das beschreibt, dass ein laufender Prozess oder Thread nicht gewaltsam von der CPU entzogen werden kann, bevor er freiwillig seine Ausführung beendet oder in einen wartenden Zustand wechselt. Dieses Konzept wird häufig in Echtzeit-Betriebssystemen und in bestimmten Scheduling-Strategien verwendet.

Details zu No Preemption:

  1. Kooperatives Multitasking:
    • In Systemen mit kooperativem Multitasking ist "No Preemption" das Standardverhalten. Ein laufender Prozess muss explizit Kontrollpunkte setzen, an denen er freiwillig die Kontrolle abgibt, damit andere Prozesse ausgeführt werden können.
  2. Deterministisches Verhalten:
    • Durch die Vermeidung von Unterbrechungen kann ein deterministisches Verhalten der Software erzielt werden, was insbesondere in sicherheitskritischen und zeitkritischen Anwendungen wichtig ist.
  3. Vorteile:
    • Weniger Kontextwechsel: Reduziert den Overhead durch weniger häufige Kontextwechsel.
    • Vorhersagbare Reaktionszeiten: Prozesse können vorhersagbare Ausführungszeiten haben, was für Echtzeitsysteme wichtig ist.
  4. Nachteile:
    • Geringere Reaktionsfähigkeit: Wenn ein Prozess nicht freiwillig die Kontrolle abgibt, können andere Prozesse lange auf die CPU-Zeit warten.
    • Risiko von Verklemmungen: Prozesse, die nicht gut programmiert sind, können das System blockieren, indem sie die Kontrolle zu lange behalten.
  5. Anwendungsbereiche:
    • Echtzeitbetriebssysteme (RTOS): Hier ist No Preemption oft gewünscht, um garantierte Antwortzeiten zu erreichen.
    • Eingebettete Systeme: Systeme, bei denen die Hardware-Ressourcen beschränkt sind und wo deterministische Antworten erforderlich sind.

Zusammengefasst bedeutet "No Preemption", dass Prozesse oder Threads nicht unterbrochen werden, bevor sie ihre aktuelle Aufgabe abgeschlossen haben, was bestimmte Vorteile in Bezug auf Vorhersagbarkeit und geringeren Overhead bietet, aber auch Nachteile hinsichtlich Reaktionsfähigkeit und Systemstabilität mit sich bringen kann.

 


Hold and Wait

"Hold and Wait" ist eine der vier notwendigen Bedingungen für das Auftreten eines Deadlocks in einem System. Diese Bedingung beschreibt eine Situation, in der ein Prozess, der bereits mindestens eine Ressource hält, zusätzlich auf weitere Ressourcen wartet, die von anderen Prozessen gehalten werden. Dies führt zu einer Situation, in der keiner der Prozesse seine Ausführung fortsetzen kann, weil jeder auf Ressourcen wartet, die von anderen Prozessen gehalten werden.

Erklärung und Beispiel

Definition

"Hold and Wait" tritt auf, wenn:

  1. Ein Prozess bereits eine oder mehrere Ressourcen hält.
  2. Der Prozess zusätzlich auf eine oder mehrere Ressourcen wartet, die von anderen Prozessen gehalten werden.

Beispiel

Betrachten wir zwei Prozesse P1P_1 und P2P_2 und zwei Ressourcen R1R_1 und R2R_2:

  • Prozess P1P_1 hält Ressource R1R_1 und wartet auf Ressource R2R_2, die von P2P_2 gehalten wird.
  • Prozess P2P_2 hält Ressource R2R_2 und wartet auf Ressource R1R_1, die von P1P_1 gehalten wird.

In diesem Szenario warten beide Prozesse auf Ressourcen, die von dem jeweils anderen Prozess gehalten werden, wodurch ein Deadlock entsteht.

Strategien zur Vermeidung von "Hold and Wait"

Um "Hold and Wait" und damit Deadlocks zu vermeiden, können verschiedene Strategien angewendet werden:

  1. Ressourcenanforderung vor Start der Ausführung:

    • Prozesse müssen alle benötigten Ressourcen anfordern und erhalten, bevor sie mit der Ausführung beginnen. Wenn nicht alle Ressourcen verfügbar sind, wartet der Prozess und hält keine Ressourcen.
function requestAllResources($process, $resources) {
    foreach ($resources as $resource) {
        if (!requestResource($resource)) {
            releaseAllResources($process, $resources);
            return false;
        }
    }
    return true;
}

Ressourcenfreigabe vor neuen Anforderungen:

  • Prozesse müssen alle gehaltenen Ressourcen freigeben, bevor sie zusätzliche Ressourcen anfordern.
function requestResourceSafely($process, $resource) {
    releaseAllHeldResources($process);
    return requestResource($resource);
}

Prioritäten und Zeitstempel:

  • Ressourcenanforderungen können priorisiert oder zeitgestempelt werden, um sicherzustellen, dass keine zyklischen Abhängigkeiten entstehen.
function requestResourceWithPriority($process, $resource, $priority) {
    if (isHigherPriority($process, $resource, $priority)) {
        return requestResource($resource);
    } else {
        // Warte oder Abbruch
        return false;
    }
}
  1. Bankiers-Algorithmus:

    • Ein algorithmischer Ansatz, der sicherstellt, dass das System immer in einem sicheren Zustand bleibt, indem es überprüft, ob die Vergabe einer Ressource zu einem unsicheren Zustand führen würde.

Zusammenfassung

"Hold and Wait" ist eine Bedingung für Deadlocks, bei der Prozesse Ressourcen halten und gleichzeitig auf weitere Ressourcen warten. Durch geeignete Strategien zur Ressourcenzuweisung und -verwaltung kann diese Bedingung vermieden werden, um die Systemstabilität und Effizienz zu gewährleisten.