05.11.2013 Aufrufe

Zahn - Unix-Netzwerkprogramminerung mit Threads, Sockets und SSL

Zahn - Unix-Netzwerkprogramminerung mit Threads, Sockets und SSL

Zahn - Unix-Netzwerkprogramminerung mit Threads, Sockets und SSL

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

3.2 Synchronisation 125<br />

97 exit( 0 );<br />

98 }<br />

28–48<br />

65<br />

77–94<br />

In der Startfunktion des Verbraucher-<strong>Threads</strong> wird nun bei jedem Schleifendurchlauf<br />

der zum gemeinsamen Puffer gehörende Mutex zunächst gesperrt<br />

<strong>und</strong> am Ende wieder freigegeben. Im dazwischen liegenden, isolierten Bereich<br />

(Zeile 33 bis Zeile 43) wird der gemeinsame Datenpuffer gelesen <strong>und</strong> geändert.<br />

Durch den gegenseitigen Ausschluß <strong>mit</strong> dem Erzeuger-Thread erfolgt der Zugriff<br />

auf diese Ressource exklusiv. Selbstverständlich müssen sich auch alle<br />

anderen <strong>Threads</strong> dieses Prozesses dazu verpflichten, das Protokoll (Sperren<br />

des Mutex, Zugriff auf die Daten, Freigabe des Mutex) strikt einzuhalten.<br />

Andernfalls wird der vereinbarte Verhaltenskodex nicht eingehalten, der exklusive<br />

Zugriff auf die gemeinsam genutzten Daten ist nicht mehr gewährleistet<br />

<strong>und</strong> eine Race Condition wäre erneut gegeben.<br />

In der Startphase des Programms ist die Initialisierung der Mutex-Variable<br />

hinzugekommen. In den meisten Fällen werden Mutex-Variablen gleich zu Beginn<br />

der main()-Funktion initialisiert, insbesondere vor dem Start der ersten<br />

<strong>Threads</strong>. Dies garantiert, daß die Mutexe auf jeden Fall bereit stehen, wenn<br />

die ersten <strong>Threads</strong> zur Synchronisation auf die Mutex-Variablen zugreifen.<br />

Wie im Verhaltenskodex festgeschrieben, hält sich auch der Erzeuger-Thread<br />

für den Zugriff auf den gemeinsamen Puffer genau an das vereinbarte Protokoll.<br />

Als erstes wird der Mutex gesperrt. Ist der Thread im Besitz des Mutex’,<br />

kann er in Ruhe einen neuen Datensatz in den Puffer einstellen. Im Anschluß<br />

an diese Operation wird der Mutex wieder freigegeben <strong>und</strong> der Erzeuger-<br />

Thread wartet auf die nächste Eingabe.<br />

Durch die besprochenen Änderungen werden in Beispiel 3.5 Race Conditions<br />

erfolgreich vermieden <strong>und</strong> das implementierte Verfahren arbeitet, ein faires<br />

Scheduling zwischen Erzeuger <strong>und</strong> Verbraucher vorausgesetzt, in jedem Fall<br />

korrekt. Allerdings weist auch diese Programmversion noch zwei Schwachstellen<br />

auf, die es zu adressieren gilt:<br />

1. Der Verbraucher-Thread rast in Erwartung eines neuen Datensatzes ohne<br />

Unterbrechung durch seine Endlosschleife. Anstatt bei leerem Datenpuffer<br />

auf einen neuen Datensatz zu warten, beendet der Thread die Schleife um<br />

sofort einen neuen Versuch zu starten.<br />

2. Der Erzeuger-Thread wartet zwar, bis ein neuer Wert eingegeben wird,<br />

versucht dann aber ohne jegliche Geduld, den Wert im Datenpuffer abzulegen.<br />

Ist der Puffer bereits voll, wird der Wert verworfen <strong>und</strong> der Anwender<br />

zur erneuten Eingabe aufgefordert, anstatt darauf zu warten, daß der<br />

nebenläufig arbeitende Verbraucher-Thread den nötigen Platz schafft.<br />

Während der Verbraucher-Thread durch seinen Dauerlauf ”<br />

lediglich“ sinnlose<br />

CPU-Last erzeugt, ist das Verhalten des Erzeuger-<strong>Threads</strong> eine Zumutung

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!