2012-06-07 18 views
5

Według specyfikacji języka lock(obj) statement; będą kompilowane jako:Jaka jest zaleta Monitor.Enter (obiekt, ref bool) nad Monitor.Enter (obiekt)?

object lockObj = obj; // (the langspec doesn't mention this var, but it wouldn't be safe without it) 
Monitor.Enter(lockObj); 
try 
{ 
    statement; 
} 
finally 
{ 
    Monitor.Exit(lockObj); 
} 

Jednak jest kompilowany jako:

try 
{ 
    object lockObj = obj; 
    bool lockTaken = false; 
    Monitor.Enter(lockObj, ref lockTaken); 
    statement; 
} 
finally 
{ 
    if (lockTaken) Monitor.Exit(lockObj); 
} 

, który wydaje się być o wiele bardziej skomplikowana, niż to konieczne. Pytanie brzmi: jaka jest zaleta tej implementacji?

Odpowiedz

5

Jak zawsze, Eric Lippert już odpowiedział następująco:

Fabulous Adventures In Coding: Locks and exceptions do not mix

+0

Już miałem odpowiedzieć sobie, gdy pomyślałem o innej odpowiedzi, która została niestety usunięta, zanim mogłem ją skomentować. Pomyślałem o tym, kiedy można rzucić wyjątki, przerwać wątki w dowolnym miejscu itd. Było oczywiste, że 'Monitor.Enter' może pomyślnie powrócić, ale zanim wątek wejdzie w blok' try', może zostać przerwany. Czasami ta strona jest zbyt szybka, aby uhonorować wszystkich ludzi, którzy pomogli znaleźć odpowiedź. – Wormbo

2

Ostatnio czytałem w "CLR via C#", że nie może faktycznie być zaletą. Rozumowanie jest takie, że blok finally zawsze zwalnia zablokowany zasób, nawet jeśli blok try został zakończony w wyniku nieoczekiwanego błędu. To może pozostawić zasób w nieokreślonym stanie i być dostępny. Program nie zakleszcza się, ale błąd może być o wiele bardziej subtelny, a przez to trudniejszy do znalezienia.

Zależy to oczywiście od sytuacji, ale domyślna wersja lock ma największe znaczenie, jeśli Twoim priorytetem jest zapobieganie zakleszczeniom w wyniku nieoczekiwanego przerwania wątków w najgorszym możliwym miejscu.

Powiązane problemy