Deadlock und Race Condition

Teil 3: Programmieren für die Multi-Core-CPU

Deadlocks

Ein Deadlock tritt immer dann auf, wenn zwei (oder mehr) Threads ein Objekt beanspruchen, das jeweils der andere Thread gerade in Besitz hat und blockiert. Deadlocks sind in keiner Weise .Net-spezifisch, sondern können in jeglichen Situationen in der IT auftreten.

Das klassische Beispiel für ein Deadlock sieht wie folgt aus:

  • Thread 1 beansprucht Objekt A

  • Thread 2 beansprucht Objekt B

  • Thread 1 braucht Zugriff auf Objekt B, muss aber warten, bis es von Thread 2 freigegeben wird. Thread 1 kann also nicht weiterlaufen (und damit eventuell Objekt B freigeben).

  • Thread 2 braucht Zugriff auf Objekt A, muss aber warten, bis es von Thread 1 freigegeben wird. Thread 2 kann also nicht weiterlaufen (und damit eventuell Objekt A freigeben).

Beide Threads blockieren sich also gegenseitig. Keiner kann weiter arbeiten, bis eine Lösung gefunden ist – meist dadurch, dass der Anwender genervt den Taskmanager bemüht und das Programm abschießt.

Vermeidung von Deadlocks

Ein genereller Ansatz zur Vermeidung von Deadlocks liegt darin, alle Objekte immer in einer festen Reihenfolge zu sperren und ferner die Sperrzeiten so gering wie möglich zu halten. Die .Net-Bibliothek stellt darüber hinaus eine Reihe von Timeouts zur Verfügung, die Deadlocks verhindern sollen.

Im folgenden Beispiel versucht jeder Codeabschnitt ein Objekt zu erhalten. Gelingt dies nicht innerhalb von 300 Millisekunden, so liefert Monitor.TryEnter FALSE zurück (Quelle Microsoft).

if (Monitor.TryEnter(this, 300)) {

try {

// Place code protected by the Monitor here.

} finally {

Monitor.Exit(this);

}

} else {

// Code to execute if the attempt times out.

}