Widzę, że w przypadku używania obiektów, które nie są bezpieczne dla wątków, kod zamykamy w taki sposób:
private static readonly Object obj = new Object();
lock (obj)
{
// thread unsafe code
}
Co dzieje się, gdy wiele wątków uzyskuje dostęp do tego samego kodu (załóżmy, że działa on w aplikacji sieci web ASP.NET). Czy są w kolejce? Jeśli tak, jak długo będą czekać?
Jaki wpływ na wydajność ma użycie blokad?
Odpowiedzi:
lock
Wypowiedź jest tłumaczona przez C # 3.0 na następujące kwestie:W C # 4.0 to się zmieniło i jest teraz generowane w następujący sposób:
Możesz znaleźć więcej informacji o tym, co tu
Monitor.Enter
robi . Aby zacytować MSDN:Monitor.Enter
Metoda będzie czekać w nieskończoność; to się nie skończy.źródło
obj
bez zakleszczenia całego systemu.lock
-statement i Monitor: abyś mógł wykonać operację w jednym wątku bez martwienia się, że inny wątek go zepsuł.To prostsze niż myślisz.
Według Microsoft :
lock
Słowo kluczowe zapewnia, że jeden wątek nie wchodzi w krytyczną sekcję kodu, podczas gdy inny wątek znajduje się w sekcji krytycznej. Jeśli inny wątek spróbuje wprowadzić zablokowany kod, zaczeka, zablokuje, aż obiekt zostanie zwolniony.Słowo
lock
kluczowe wywołujeEnter
na początku bloku iExit
na końcu bloku.lock
słowo kluczowe faktycznie obsługujeMonitor
klasę z tyłu.Na przykład:
W powyższym kodzie najpierw wątek wchodzi do sekcji krytycznej, a następnie zostanie zablokowany
obj
. Gdy inny wątek próbuje wejść, spróbuje również zablokowaćobj
, który jest już zablokowany przez pierwszy wątek. Drugi wątek będzie musiał poczekać na zwolnienie pierwszego wątkuobj
. Kiedy pierwszy wątek opuści, kolejny wątek zostanie zablokowanyobj
i przejdzie do sekcji krytycznej.źródło
Nie, nie są w kolejce, śpią
Instrukcja blokady formularza
gdzie x jest wyrażeniem typu odniesienia, jest dokładnie równoważne z
Musisz tylko wiedzieć, że czekają na siebie, a tylko jeden wątek wejdzie, aby zablokować blok, pozostałe zaczekają ...
Monitor jest w pełni napisany w .net, więc jest wystarczająco szybki, spójrz także na klasę Monitor z reflektorem, aby uzyskać więcej szczegółów
źródło
lock
instrukcji nieznacznie zmienił się w C # 4: blogs.msdn.com/b/ericlippert/archive/2009/03/06/…Zamki będą blokować inne wątki przed wykonaniem kodu zawartego w bloku zamka. Wątki będą musiały poczekać, aż wątek w bloku zamka zostanie zakończony i zamek zostanie zwolniony. Ma to negatywny wpływ na wydajność w środowisku wielowątkowym. Jeśli musisz to zrobić, upewnij się, że kod w bloku blokady może być przetwarzany bardzo szybko. Powinieneś starać się unikać kosztownych działań, takich jak dostęp do bazy danych itp.
źródło
Wpływ na wydajność zależy od sposobu blokowania. Dobrą listę optymalizacji można znaleźć tutaj: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/
Zasadniczo powinieneś spróbować zablokować tak mało, jak to możliwe, ponieważ powoduje to uśpienie kodu oczekiwania. Jeśli masz jakieś ciężkie obliczenia lub trwały kod (np. Przesyłanie pliku) w zamku, powoduje to ogromną utratę wydajności.
źródło
do { oldValue = thing; newValue = updated(oldValue); } while (CompareExchange(ref thing, newValue, oldValue) != oldValue
]. Największym niebezpieczeństwem jest to, że jeśli wymagania ewoluują poza to, co takie techniki mogą obsłużyć, dostosowanie kodu do tego może być trudne.Część w instrukcji lock może być wykonana tylko przez jeden wątek, więc wszystkie pozostałe wątki będą czekać w nieskończoność na zakończenie wątku zawierającego blokadę. Może to spowodować tzw. Impas.
źródło
lock
Wypowiedź jest tłumaczona na wezwania doEnter
iExit
metodMonitor
.lock
Oświadczenie będzie czekać w nieskończoność na obiekt blokujący ma zostać wydany.źródło
blokada jest w rzeczywistości ukryta klasa Monitor .
źródło