2009-08-25 11 views

Odpowiedz

15

Powodem, dla którego ta blokada jest konstrukcją językową, a kompilator decyduje się na nałożenie dodatkowej semantyki na wyrażenie. Monitor.Enter jest po prostu wywołaniem metody, a kompilator C# nie traktuje w specjalny sposób wywołania w żaden sposób, a zatem przechodzi przez normalną rozdzielczość przeciążania i boks.

0

powiedziałbym, że to dlatego, Monitor.Enter() jest wywołanie metody, więc kompilator wykonuje boks automatycznie, natomiast lock() jest elementem składniowym, więc kompilator może sprawdzić i wygeneruje błąd na typów wartości.

+0

Nie sądzę, że istnieje jakakolwiek kontrola. Czy blokada nie została rozwinięta za pomocą Monito.Enter w bloku try i Monitor.Exit w bloku finally. – Sandbox

+1

nie jest rozszerzony do tego, ale najpierw kompilator spostrzega, jeśli jesteś głupi w drodze ... – ShuggyCoUk

11

Zdecydowanie nie należy używać Monitor.Enter na urządzeniu int. Powodem, dla którego działa, jest fakt, że int jest zapakowany w pudełka, więc jeśli nie zapiszesz odwołania do wartości pudełkowej, zablokujesz tymczasowy obiekt, co oznacza, że ​​nie możesz zadzwonić pod numer Monitor.Exit bez uzyskania wyjątku.

Zalecanym sposobem wykonania blokady jest utworzenie private readonly object i zablokowanie tego. W przypadku metody statycznej można użyć wartości private static object.

3

Po prostu z ciekawości, co robisz ze zmienną "i", która wymaga jej zablokowania? To może być bardziej efektywne użycie zblokowane klasy, jeśli wszystko robisz jest przyrost lub coś:

Interlocked.Increment(i); // i++ in a thread safe manner 

powiązanej klasa jest najlżejszym wątek masa narzędzia synchronizacji zapewnia, że ​​.NET, a dla prostych krokach, ubytki, czyta lub wymiany, to najlepsza opcja.

Jeśli próbujesz zsynchronizować blok zachowanie, to bym po prostu utworzyć obiekt, który może być używany jako korzeń Synchronizacja:

object syncRoot = new object(); 

// ... 

lock(syncRoot) 
{ 
    // put synced behavior here 
} 
+0

wyłącznie w interesie ... jestem świadomy klasy Interlocked. Dzięki. – Sandbox

5

W specyfikacji kompilatora określa the behaviour of lock like so:

Typ czasu kompilacji wyrażenia instrukcji lock jest typem referencyjnym lub parametrem>> type (§25.1.1), znanym jako typ referencyjny. Jest to błąd kompilacji dla typu kompilacji czasu określający typ wartości.

Następnie określa, co jest równoznaczne z tak długo, jak to kompiluje

Rejestracja Monitor.Exit to po prostu wywołanie metody bez żadnych ograniczeń, które nie uniemożliwi kompilatorowi automatycznie boksowania int i kontynuowania jego wesołego (i bardzo) niewłaściwego sposobu.

lock NIE jest po prostu cukrem syntaktycznym w taki sam sposób, jak foreach nie jest po prostu cukrem syntaktycznym. Powstała transformacja IL jest , a nie przedstawiona pozostałym fragmentom kodu, tak jakby to było napisane.

Nieprawidłowe jest modyfikowanie zmiennej iteracji (mimo, że nie ma nic na poziomie IL w wynikowym kodzie, który mógłby temu zapobiec). W blokadzie kompilator zapobiega kompilacji znanych typów wartości, ponownie pomimo wynikłego IL nie dbającego o to.

Tak na marginesie:
Teoretycznie kompilator może być „błogosławiony” z intymnej znajomości tego (i innych) metod tak, że dostrzeżone oczywiste przypadki takiej sytuacji, ale zasadniczo jest to niemożliwe zawsze dostrzec to co czas kompilacji (należy rozważyć przekazanie obiektu z innej metody, złożenia lub odbicia), więc niepotrzebne jest wykrycie takich przypadków, które prawdopodobnie byłyby nieproduktywne.

Im więcej kompilator wie o wewnętrznych cechach API, tym więcej problemów będzie można uzyskać, jeśli w przyszłości będzie trzeba zmienić interfejs API.

Możliwe jest na przykład dodanie przeciążenia metody Monitor.Enter(), która zajęła wartość int i zablokowała cały proces związany z wartością int.
Byłoby to zgodne ze specyfikacją monitora (nawet jeśli byłoby to prawdopodobnie ohydne), ale powodowałoby ogromne problemy dla starszego kompilatora, który nadal radośnie uniemożliwiał operację, która stała się legalna.

+0

Dobra odpowiedź. Dzięki. – Sandbox

Powiązane problemy