Erfolgreiche ePaper selbst erstellen
Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.
200<br />
10 <strong>Race</strong> <strong>Conditions</strong><br />
Denn ein geänderter Compiler-Schalter, ein neues printf zu Debug-Zwecken oder<br />
ein geändertes Speichermodell verändern das Laufzeitverhalten des Systems und<br />
können den Fehler somit unsichtbar machen.<br />
Ein Data <strong>Race</strong> um eine Variable x zwischen zwei oder mehreren Threads<br />
kann nur dann vorkommen, wenn:<br />
■ zumindest ein Zugriff auf x schreibend ist und<br />
■ die Threads keinen Mechanismus verwenden, der den gleichzeitigen Zugriff<br />
auf x verhindert. So ein Mechanismus wird im folgenden Absatz vorgestellt.<br />
Locking von kritischen Code-Passagen<br />
Ein Lock ist ein meist vom Betriebssystem zur Verfügung gestellter Synchronisationsmechanismus.<br />
Dieser wird zum Schutz gemeinsam benutzter Ressourcen vor<br />
Zugriffen von verschiedenen Threads verwendet. Ein Lock wird auch als Mutex<br />
bezeichnet und ähnelt einem binären Semaphor. »Mutex« kommt von »mutual<br />
exclusion«, also dem gegenseitigen Ausschluss zweier oder mehrerer Threads.<br />
Erhält ein Thread A ein Lock (in der Modellvorstellung entspricht ein Lock<br />
einem Schlüssel) zu einer kritischen Code-Passage, dann wird jeder andere<br />
Thread B, der nach dem Schlüssel verlangt, so lange angehalten, bis Thread A den<br />
Schlüssel wieder freigibt. Die dazu passenden, vom Betriebssystem zur Verfügung<br />
gestellten Routinen heißen entsprechend meist ähnlich zu lock_obtain() und<br />
lock_release() oder lock() und unlock(). Der Parameter der Routinen ist der<br />
Name des Schlüssels. Es können also verschiedene Schlüssel verwendet werden,<br />
die verschiedene kritische Code-Passagen schützen. In Listing 10–3 ist ein Fix des<br />
Problems von Listing 10–1 mit Hilfe von Locks zu sehen.<br />
#include <br />
#include <br />
extern int is_prime(int);<br />
void zaehler1(void); /* Thread 1 */<br />
void zaehler2(void); /* Thread 2 */<br />
int primzahlen = 0; /* so viele PZ gefunden */<br />
rtos_id id_lock, /* Schutz f. Primzahlen*/<br />
id_thread1, id_thread2;<br />
int main(void)<br />
{<br />
rtos_id id_thread1, id_thread2;<br />
rtos_lock_create(UNLOCKED, &id_lock);<br />
rtos_thread_create(ROUND_ROBIN_SCHEDULING, &id_thread1);<br />
rtos_thread_create(ROUND_ROBIN_SCHEDULING, &id_thread2);<br />
rtos_thread_start(id_thread1, zaehler1);<br />
rtos_thread_start(id_thread2, zaehler2);