Czy poniższy kod spowoduje zakleszczenie przy użyciu języka C # na platformie .NET?
class MyClass
{
private object lockObj = new object();
public void Foo()
{
lock(lockObj)
{
Bar();
}
}
public void Bar()
{
lock(lockObj)
{
// Do something
}
}
}
Odpowiedzi:
Nie, pod warunkiem, że blokujesz ten sam obiekt. Kod rekurencyjny skutecznie już posiada blokadę i może działać bez przeszkód.
lock(object) {...}
jest skrótem do używania klasy Monitor . Jak wskazuje Marc ,Monitor
pozwala na ponowne wejście , więc wielokrotne próby zablokowania obiektu, na którym bieżący wątek ma już blokadę, będą działać dobrze.Jeśli zaczniesz blokować różne obiekty, wtedy musisz być ostrożny. Zwróć szczególną uwagę na:
Jeśli złamiesz którąkolwiek z tych zasad, masz prawie gwarancję, że w pewnym momencie wystąpią problemy z zakleszczeniem .
Oto jedna dobra strona internetowa opisująca synchronizację wątków w .NET: http://dotnetdebug.net/2005/07/20/monitor-class-avoiding-deadlocks/
Ponadto blokuj jak najmniej obiektów naraz. W miarę możliwości rozważ zastosowanie gruboziarnistych zamków . Chodzi o to, że jeśli możesz napisać swój kod w taki sposób, że istnieje graf obiektowy i możesz uzyskać blokady w katalogu głównym tego grafu obiektowego, zrób to. Oznacza to, że masz jedną blokadę na tym obiekcie root i dlatego nie musisz się tak bardzo martwić o kolejność, w której nabywasz / zwalniasz blokady.
(Jeszcze jedna uwaga, twój przykład nie jest technicznie rekurencyjny. Aby był rekurencyjny,
Bar()
musiałby wywołać siebie, zwykle jako część iteracji.)źródło
Cóż,
Monitor
pozwala na ponowne entuzjazm, więc nie możesz się zablokować ... więc nie: nie powinnoźródło
Jeśli wątek już trzyma blokadę, nie będzie się blokował. Zapewnia to framework .Net. Musisz tylko upewnić się, że dwa wątki nie próbują uzyskać tych samych dwóch blokad poza kolejnością przez jakiekolwiek ścieżki kodu.
Ten sam wątek może wielokrotnie uzyskać tę samą blokadę, ale musisz upewnić się, że zwalniasz blokadę taką samą liczbę razy, jak ją zdobywasz. Oczywiście, o ile używasz do tego słowa kluczowego „lock”, dzieje się to automatycznie.
źródło
Nie, ten kod nie będzie miał martwych zamków. Jeśli naprawdę chcesz stworzyć zakleszczenie, najprostszy wymaga co najmniej 2 zasobów. Rozważ scenariusz dotyczący psa i kości. 1. Pies ma pełną kontrolę nad 1 kością, więc każdy inny pies musi czekać. 2. Wymagane jest minimum 2 psów z 2 kośćmi, aby doprowadzić do impasu, gdy odpowiednio blokują swoje kości i szukają kości innych.
... tak dalej i tak dalej n psów i m kości i powodują bardziej wyrafinowane zakleszczenia.
źródło