Vorheriger Beitrag: Nützliche Online-Infos rund ums Parallele Programmieren
Workshop: Alles über .NET-Threads – Teil 4
Eine neue Woche beginnt, und im selben Atemzug endet meine vierteilige Serie zum Thema .NET-Threads. So habe ich im ersten Kapitel über das Erzeugen von Threads geschrieben, im zweiten Teil mich über das Verwalten derselben ausgelassen, und am letzten Donnerstag war der ThreadPool und dessen Möglichkeiten dran. Und heute?! Nun, heute geht es um die Synchronisierung mehrerer Threads und atomare Aktionen.
Zunächst einmal kann man festhalten, dass die Thread-Synchronisierung im .NET-Framework ähnlich funktioniert wie im Win32- oder Pthreads-Umfeld. Es geht also um den gegenseitigen Ausschluss sowie um atomare Aktionen auf spezielle Variablen. Wie bei der von C# bekannten Methode lock wird ein Codeabschnitt mithilfe der geschweiften Klammern geblockt, sodass zu dieser Zeit nur ein einziger Thread darauf zugreifen kann. Hierfür bietet das .NET-Framework eine ähnliche Konstrukte:
Monitor.Enter ( this )
try
{
……. shared_var = other_shared_var +1;
……. other_shared_var = 0;
}
finally
{
…… Monitor.Exit ( this )
}
Mit der Klasse Monitor wird der entsprechende Codeabschnitt blockiert. Mit Enter() wird der Abschnitt gesperrt und mit Exit() wieder freigegeben. Praktisch an Monitor ist auch dessen Möglichkeit, Datenstrukturen als Parameter zu übergeben.
Bei Monitor.Enter() geschehen übrigens zwei Dinge: Erstens wird eine Warteschlange eingerichtet, die auf diejenigen Threads verweist, die gesperrt werden sollen und eine zweite Queue mit Threads, die darüber informiert werden wollen, wenn eine Speere verfügbar ist. Monitor.Exit() sorgt dafür, dass der erste verfügbare Thread in Warteschlange #1 gesperrt wird.
Darüber hinaus hält die Klasse Monitor eine weitere Methode bereit: So lässt sich mit Monitor.Wait() die Sperre eines Threads auf einen anderen Thread übertragen, um die Sperre später wieder zurückzuverlangen. Ein Impuls benachrichtigt hierbei den ursprünglichen Thread darüber, dass die Sperre wieder aufgehoben wurde.
Neben den Monitor-Methoden lassen sich unter .NET auch Mutexe für das Sperren und Freigeben von Threads verwenden. Im Gegensatz zu der Monitor-Klasse werden Mutexe in Verbindung mit Handles eingesetzt und können zudem zudem für mehrere Sperren eingesetzt werden, die dann natürlich genauso oft wieder freigegeben werden.
private static Mutex mutx = new Mutex();
…
private static void UseResource()
{
……//Warten, um in den Sperrcode einzutreten
……mutx.WaitOne();
……Console.WriteLine( ” im gesperrten Modus “);
……Thread.Sleep( 100 ); // 100 Millisekunden warten
……Console.WriteLine( ” den gesperrten Modus wieder verlassen “);
……// Mutex wieder freigeben
……mutx.ReleaseMutex();
}
Atomare Aktionen
Unter atomaren Aktionen versteht man landläufig unteilbare Maschinenanweisungen, wie sie beispielsweise für Datenbankoperationen eingesetzt werden. Dabei ist es von essenzieller Wichtigkeit, dass mehrere dieser Teilschritte zurückgenommen werden können, falls der gesamte Schritt nicht beendet werden kann. Bei Threads verhält es sich ganz ähnlich: Variablen werden verändert und gleichzeitig geht beim Programmablauf etwas schief. Die Folge: Das System ist im schlimmsten Fall beschädigt oder Daten korrupt.
Um so etwas auszuschließen, hat Microsoft in das .NET-Framework die Klasse Interlock eingebaut, die drei wesentliche Methoden vorsieht: Decrement, Increment und Exchange. Diese sollten vor allem dann eingesetzt werden, wenn eine bestimmte Variable von mehreren Threads parallel genutzt wird:
int intCounter = 0;
…
Interlocked.Exchange( ref usingResource, 6 ); // Setze den Wert von intCounter auf 6
Interloced.Decrement( ref intCounter ); // Reduziere den Wert von intCounter auf 5
Interlocked.Increment( ref intCounter ); // Erhöhe den Wert von intCounter wieder auf 6
Beachtenswert ist die Tatsache, dass mit Increment und Decrement nicht die Variable selbst, sondern nur der Verweis darauf verändert wird (da es sich dank des Zusatzes ref um eine Art Zeiger handelt). Und Exchange ändert nicht die Werte, sondern initialisiert lediglich einen Wert mit einem anderen.

Kommentare
Keine Kommentare vorhanden.