3.2.11.2 Aktives Warten

[gesichtete Version][gesichtete Version]
Keine Bearbeitungszusammenfassung
Zeile 3: Zeile 3:
<loop_index>Aktives Warten|Warten, aktiv|Geschäftiges Warten|Busy Waiting</loop_index>
<loop_index>Aktives Warten|Warten, aktiv|Geschäftiges Warten|Busy Waiting</loop_index>
'''Aktives Warten''', manchmal auch als '''Geschäftiges Warten''' oder auf Englisch '''Busy Waiting''' bezeichnet, ist eine recht einfache Technik, um Prozesse oder Threads zu synchronisieren.
'''Aktives Warten''', manchmal auch als '''Geschäftiges Warten''' oder auf Englisch '''Busy Waiting''' bezeichnet, ist eine recht einfache Technik, um Prozesse oder Threads zu synchronisieren.
</p>
<p>
<loop_area type="notice">
<p>
Findest du heraus, welchen großen Nachteil ''aktives Warten'' besitzt?<br />
<small>Lies' mal weiter, wir kommen ganz am Ende dieser Seite auf diese Frage zurück.</small>
</p>
</loop_area>
</p>
</p>


Zeile 23: Zeile 14:
</p>
</p>
</loop_area>
</loop_area>
</p>
<p>
Die Technik des ''ständigen Abfragens'' ist in der Informatik auch als ''Polling'' bekannt. Das genannte ''Sperrkennzeichen'' kann eine von mehreren Prozessen oder Threads gemeinsam genutzte Variable sein, man spricht dann von einer ''Sperrvariable''. Das folgende Beispiel geht darauf ein.
</p>
</p>


<br />
<br />
 
== Polling ==
== Beispiel für aktives Warten ==
<p>
<p>
Der Code des bereits bekannten [[Kritischer_Abschnitt#Beispiel_zu_kritischen_Abschnitten|Beispiels zu kritischen Abschnitten]] wird um eine (globale) Sperrvariable erweitert, beide Threads haben damit Zugriff auf diese Variable:
Die Technik des ''ständigen Abfragens'' ist in der Informatik auch als ''Polling'' bekannt. Das genannte ''Sperrkennzeichen'' kann eine von mehreren Prozessen oder Threads gemeinsam genutzte Variable sein, man spricht dann von einer ''Sperrvariable''. Das folgende Beispiel geht darauf ein.
</p>
 
<p>
<loop_area type="sourcecode">
<p>
<span style="font-family:Courier">
static int lock = 0;
</span>
</p>
</loop_area>
</p>
 
<p>
Besitzt <span style="font-family:Courier">lock</span> den Wert Null, so definiert man, dass sich aktuell kein Prozess oder Thread in seinem kritischen Abschnitt befindet. Der kritische Abschnitt darf also betreten werden, dabei muss <span style="font-family:Courier">lock</span> auf Eins gesetzt werden.
</p>
<p>
Direkt bevor der kritische Abschnitt wieder verlassen wird, wird <span style="font-family:Courier">lock</span> auf Null zurück gesetzt.
</p>
<p>
Alle beteiligten Prozesse oder Threads müssen beim Betreten eines kritischen Bereichs den Wert von <span style="font-family:Courier">lock</span> prüfen, und gegebenenfalls warten.
</p>
 
<p>
<loop_area type="sourcecode">Beim Betreten des kritischen Abschnitts:
<p>
<span style="font-family:Courier">
while (lock == 1);<br />
lock = 1;
</span>
</p>
</loop_area>
</p>
 
<p>
<loop_area type="sourcecode">Direkt vor dem Verlassen des kritischen Abschnitts:
<p>
<span style="font-family:Courier">
lock = 0;
</span>
</p>
</loop_area>
</p>
 
<br />
== Aufgabe 1 ==
<p>
<loop_area type="task">
<loop_task title="Die Bedeutung des Semikolons!">
<p>
Die Codezeile
</p>
<p>
<span style="font-family:Courier">while (lock == 1);</span>
</p>
<p>
ist sehr wichtig. Hier wird der Wert von <span style="font-family:Courier">lock</span> geprüft und gegebenenfalls gewartet. Die Sache mit dem Warten kannst du aber nur verstehen, wenn du die Bedeutung des Semikolons ganz am Ende der Codezeile kennst.
</p>
<p>
Erläutere:<br />
Welche Bedeutung hat das Semikolon in Verbindung mit dem <span style="font-family:Courier">while</span>?
</p>
<p>
Und was würde passieren, wenn das Semikolon versehentlich fehlt:
</p>
<p>
<span style="font-family:Courier">
while (lock == 1) &nbsp; &nbsp; &nbsp; &nbsp;// Hier fehlt das Semikolon, Programmierfehler!<br />
lock = 1;
</span>
</p>
<p>
<small>(PS.: Die <span style="font-family:Courier">while</span>-Schleife ist auch der Grund für den großen Nachteil des aktiven Wartens, siehe letzte Aufgabe ganz unten auf dieser Seite!)</small>
</p>
</loop_task>
</loop_area>
</p>
 
<br />
<p>
Nachdem nun bekannt ist, welcher Code zur Implementierung des aktiven Wartens notwendig ist, kann dieser an den entsprechenden Stellen des [[Kritischer_Abschnitt#Beispiel_zu_kritischen_Abschnitten|Beispielprogramms]] eingepflegt werden.
</p>
 
<br />
 
== Aufgabe 2 ==
<p>
<loop_area type="task">
<loop_task title="Aktives Warten implementieren">
<p>
Tu es! Füge den für das aktive Warten nötigen Code dem [[Kritischer_Abschnitt#Beispiel_zu_kritischen_Abschnitten|Beispielprogramm]] hinzu.
</p>
<spoiler text="Lösung">
<p>
<loop_listing title="Beispiel: Aktives Warten" description="Ein Java-Programm mit zwei Threads. Die Sperrvariable soll ein gleichzeitiges Betreten der kritischen Abschnitte durch beide Threads verhindern.">
<source lang="java" line="true">
public class Beispiel_Aktives_Warten {
 
static int counter = 0;      // gemeinsam genutztes Betriebsmittel
static int lock = 0;          // Sperrvariable
 
public static class Thread_A extends Thread {
public void run() {
do_something();          // unkritisch
count_from_10();        // kritisch !!!
do_something_else();    // unkritisch
}
private void do_something() {
// unkritischer Abschnitt
System.out.println("Thread_A: unkritisch");
}
private void count_from_10() {
// Vorsicht: kritischer Abschnitt!
while (lock == 1);      // Semikolon beachten!
lock = 1;
 
counter = 10;
counter++;
counter++;
System.out.println("A-Counter: " + counter);
 
lock = 0;
}
private void do_something_else() {
// unkritischer Abschnitt
System.out.println("Thread_A: wieder unkritisch");
}
}
public static class Thread_B extends Thread {
public void run() {
System.out.println("Thread_B ist gestartet.");
while (lock == 1);      // Semikolon beachten!
lock = 1;
 
counter = 20;
counter++;
counter++;
counter++;
counter++;
counter++;
counter++;
System.out.println("B-Counter: " + counter);
 
lock = 0;
}
}
 
public static void main(String[] args) {
Thread a = new Thread_A();
Thread b = new Thread_B();
a.start();
b.start();
}
 
}
</source>
</loop_listing>
</p>
</spoiler>
</loop_task>
</loop_area>
</p>
 
<br />
<p>
<loop_area type="notice">
<p>
In dieser Lösung wird wieder gezeigt, wie zwei Threads durch die Sperrvariable beeinflusst werden. Es hat den Anschein, als ob ein Anwendungsprogrammierer sich darum kümmern müsste. <small>(Das muss er nur bei den von ihm selbst geschaffenen "Betriebsmitteln". Es sei erneut auf das für diese Zwecke in Java integrierte Schlüsselwort [http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html synchronized] verwiesen.)</small>
</p>
<p>
Du musst gedanklich hier wieder den Sprung zu Prozessen schaffen, und zu den vielen Betriebsmitteln eines Computersystems, und zum Betriebssystem, und zu Systemaufrufen, über die letztlich das aktive Warten durch das Betriebssystem realisiert werden kann.
</p>
<p>
Dann verstehst du, dass sich der '''Programmierer des Betriebssystems''' darum kümmern muss!
</p>
</loop_area>
</p>
 
<br />
 
== Aufgabe 3 ==
<p>
<loop_area type="task">
<loop_task title="Warte aktiv!">
<p>
Spiele in deiner Lerngruppe das Verhalten der beiden Threads aus der [[Aktives_Warten#Aufgabe_2|Lösung zu Aufgabe 2]] durch. Bedenke:
* Es gibt nur eine CPU mit einem Kern. Es kann also nur ein Prozess zur Zeit ausgeführt werden, es kommt zu Quasi-Parallelität.
* Interessant ist die Situation, bei der sich bereits ein Prozess in seinem kritischen Abschnitt befindet, und die Sperre gesetzt hat.
* Der Kontextwechsel erfolgt, und der andere Prozess muss dann an der <span style="font-family:Courier">while</span>-Schleife warten. Tut er das?
</p>
</loop_task>
</loop_area>
</p>
 
<br />
 
== Aufgabe 4 ==
<p>
<loop_area type="task">
<loop_task title="Der Nachteil des aktiven Wartens">
<p>
Welchen großen Nachteil besitzen alle Verfahren, die nach dem Prinzip des aktiven Wartens verfahren?
</p>
<spoiler text="Tipp">
<p>
Gemeint ist hier ein ''zeitlicher Nachteil''. Denk mal daran, wie sinnvoll die CPU beschäftigt wird. Wie wirkt sich das deiner Meinung nach auf die Performance des Gesamtsystems aus?
</p>
</spoiler>
</loop_task>
</loop_area>
</p>
</p>



Version vom 6. Februar 2015, 11:33 Uhr

Aktives Warten

Aktives Warten, manchmal auch als Geschäftiges Warten oder auf Englisch Busy Waiting bezeichnet, ist eine recht einfache Technik, um Prozesse oder Threads zu synchronisieren.


Definition: Aktives Warten

Definition

Unter aktivem Warten versteht man nach Mandl 2013 das ständige Abfragen eines Sperrkennzeichens am Eingang eines kritischen Abschnitts.


Polling

Die Technik des ständigen Abfragens ist in der Informatik auch als Polling bekannt. Das genannte Sperrkennzeichen kann eine von mehreren Prozessen oder Threads gemeinsam genutzte Variable sein, man spricht dann von einer Sperrvariable. Das folgende Beispiel geht darauf ein.



Diese Seite steht unter der Creative Commons Namensnennung 3.0 Unported Lizenz http://i.creativecommons.org/l/by/3.0/80x15.png