Aktives Warten

aus Wikipedia, der freien Enzyklopädie
Dies ist die aktuelle Version dieser Seite, zuletzt bearbeitet am 20. Mai 2021 um 05:40 Uhr durch imported>Filzstift(1859) (→‎Nachteile: eben: "moderne Programmierung": Nur wenn die CPU das unterstützt. Bei vielen kleinen low-speed-8-bit-MCU kein Thema.).
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

Aktives Warten (auch Verzögerungsschleife; englisch busy waiting oder

spinning

) bezeichnet eine Aktivität eines Computerprogramms, mit der die Zeit bis zur Erfüllung einer Bedingung aktiv, d. h. durch Ausführung von Anweisungen, welche den Zustand des Programms nicht verändern, überbrückt wird.

Implementierung

Aktives Warten wird mittels wiederholt auszuführenden Anweisungen, mit denen geprüft wird, ob die Bedingung erfüllt ist, implementiert:

solange (Bedingung b nicht erfüllt) {
   tue nichts;
}

Aktives Warten nutzt offensichtlich Prozessorkapazität für die sofortige, wiederholte Überprüfung, ob die Bedingung erfüllt ist. In seiner reinen Form werden außer der Überprüfung keine weiteren Aktionen ausgeführt.

Anwendungen

Zeitüberbrückung

Aktives Warten wurde oft eingesetzt, um eine Zeitspanne einer gegebenen Länge zu überbrücken. Die Länge der zu überbrückenden Zeitspanne wurde unter Berücksichtigung der Ausführungsdauer einer Iteration der Schleife vom Programmierer in eine Anzahl zu durchlaufender Iterationen umgerechnet:

int i = 0;
while (i < n) {
   i = i + 1;
}

Moderne Programmierung verwendet Hardware-Timer, um eine bestimmte Zeitspanne abzuwarten; aktives Warten wird nur eingesetzt, wenn kein solcher Timer verfügbar oder die abzuwartende Zeitspanne sehr kurz ist.

Synchronisation

Häufiger als zur Zeitüberbrückung wird aktives Warten zur Synchronisation der Aktivitäten parallel laufender/arbeitender Komponenten eines Rechensystems eingesetzt. Bei den Komponenten handelt es sich entweder nur um Software-Komponenten (Prozesse bzw. Threads) oder um Software- und Hardware-Komponenten, die miteinander kooperieren. In Synchronisationssituationen wird die Reihenfolge, in der die Aktionen der Komponenten ausgeführt werden, geregelt, da eine beliebige parallele oder zeitlich verschränkte Ausführung der Aktionen unerwünscht ist.

Gebräuchlich ist der Einsatz von aktivem Warten zur Synchronisation in folgenden Situationen:

Zustandsabfrage
Eine Komponente A (eine Software-Komponente) kann erst dann mit ihren Aktionen fortsetzen, wenn eine Komponente B (oftmals ein Gerät) einen bestimmten Zustand erreicht hat. Das Erreichen des Zustands in der Komponente B wird auf eine Weise angezeigt, die eine Prüfung durch die Komponente A zulässt (s. Memory Mapped I/O). Komponente A setzt dann aktives Warten ein, um zu verhindern, dass sie bereits Aktionen ausführt, obwohl dies der Zustand der Komponente B noch nicht zulässt. Das aktive Warten wird dann auch polling genannt.
Oft ist es ausreichend, die Zustandsabfrage nicht ununterbrochen vorzunehmen:
solange (Bedingung b nicht erfüllt) {
   warte für einige Zeit;
}
Diese Variante des aktiven Wartens wird auch als slow busy waiting oder lazy polling bezeichnet. Voraussetzung für einen nutzbringenden Einsatz ist jedoch, dass mit Hilfe eines Betriebssystems oder einer Laufzeitumgebung die freigewordene Prozessorkapazität genutzt wird, um ein anderes Programm vom Prozessor ausführen zu lassen. Nachteilig an der Variante ist neben der nach wie vor vorhandenen, wenn auch verringerten Verschwendung von Prozessorkapazität, dass oftmals länger als nötig gewartet wird, weil die Bedingung erst nach Ablauf der Wartezeit wieder geprüft wird.
Abfrage einer Sperre
Wird zur Synchronisation der Aktivitäten von Software-Komponenten (Prozessen bzw. Threads) speziell eine gemeinsam genutzte Variable vereinbart und wird mit einer Veränderung des Variablenwerts angezeigt, dass ein Prozess/Thread mit seinen Aktionen fortsetzen kann, so verwendet der Prozess/Thread aktives Warten, um die Veränderung zu erkennen:
Gemeinsam von A und B genutzte Variable: lock
Interpretation des Werts:                0 gesperrt, ungleich 0 offen 
Initialisierung:                         lock = 0
       
Prozess A                    Prozess B
   ...                          ...
   solange (lock == 0) {        ...
      ;                         lock = 1;
   }                            ...
   Aktion a                     ...
Da die Variable lock verhindert, dass der Prozess/Thread A die Aktion a unkontrolliert durch B fortsetzt, wird die Variable Sperrvariable (Lock) genannt. Da die Veränderung der Variable mittels wiederholtem (drehendem) Abfragen festgestellt wird, spricht man auch von einem Spinlock. Spinlocks sind ein grundlegendes Konzept der Prozesssynchronisation.

Nachteile

Sofern die CPU ein Stromsparmodus kennt, verhindert aktives Warten, dass die CPU in den Stromsparmodus wechseln kann. Es verbraucht damit unnötig Energie, erzeugt abzuführende Wärme und damit ggf. Lüfterlärm; zudem lässt Wärme die CPU auch schneller altern.

Siehe auch