2009-03-13 11 views
8

Czy nie byłoby to przesadą i konieczne jest tylko jedno z nich? Wyszukiwanie i znajdowanie różnych wpisów dotyczących wzajemnego wykluczania i blokad w C# here i here.

Przykład:
W naszej aplikacji mamy funkcję, która obraca wiele wątków ponownego połączenia, a wewnątrz tego wątku używamy Mutex i lock. Czy nie zablokuje dostępu do tej sekcji kodu i uniemożliwi aktualizację connect przez inny wątek?Czy blokady i Mutexy w języku C# powinny być używane razem?

bool connect = false; 
Mutex reconnectMutex = new Mutex(false, "Reconnect_" + key); 

try 
{ 
    lock(site) 
    { 
     if(site.ContainsKey(key)) 
     { 
     siteInfo = (SiteInfo)site[key]; 
     if(reconnectMutex.WaitOne(100, true)) 
     { 
      connect = true; 
     } 
     } 
    } 

    if (connect) 
    { 
     // Process thread logic 
    } 
} 
catch 
{} 

reconnectMutex.ReleaseMutex(); 

Więcej informacji:
to w sposób WebService ASP.NET nie działa w Ogrodzie internetowej.

Odpowiedz

11

Ten Mutex (ponieważ ma nazwę) zatrzyma każdy proces na tej samej maszynie, która uzyskuje dostęp do niego, podczas gdy blokada zatrzyma tylko inne wątki w tym samym procesie. Z tego kodu źródłowego nie widzę, dlaczego potrzebujesz obu rodzajów zamka. Wydaje się, że dobrą praktyką jest trzymanie prostej blokady przez krótki okres czasu - ale wtedy znacznie cięższy muteks międzyprocesowy jest zablokowany na prawdopodobnie dłuższy (choć nakładający się) okres! Byłoby łatwiej użyć po prostu muteksu. A może dowiedzieć się, czy blokada międzyprocesowa jest naprawdę potrzebna.

Przy okazji, catch {} jest absolutnie niewłaściwą rzeczą w tym scenariuszu. Powinieneś użyć finally { /* release mutex */ }. Są bardzo różne. Połów pochłonie znacznie więcej rodzajów wyjątkiem niż powinien, i spowoduje również zagnieżdżone w końcu koparki do wykonania w odpowiedzi na niskopoziomowych wyjątkami, takimi jak uszkodzenia pamięci, naruszenia zasad dostępu, itp więc zamiast:

try 
{ 
    // something 
} 
catch 
{} 

// cleanup 

powinieneś mieć:

try 
{ 
    // something 
} 
finally 
{ 
    // cleanup 
} 

A jeśli istnieją szczególne wyjątki można odzyskać od, można je złapać:

try 
{ 
    // something 
} 
catch (DatabaseConfigurationError x) 
{ 
    // tell the user to configure the database properly 
} 
finally 
{ 
    // cleanup 
} 
+0

należy jednak odpowiednio nazwać maszynę. –

+0

Dobra sprawa, mam nadzieję, że wyjaśniono to w pierwszym zdaniu. –

+0

Chcesz powiedzieć, że powinienem wyeliminować oświadczenie połowowe i zastąpić je ostatecznie? –

3

„lock” jest w zasadzie tylko cukier syntaktyczny dla Montor.Enter/Exit. Mutex to blokada wieloprocesowa.

Mają bardzo różne zachowanie. Nie ma nic złego w używaniu obu w tej samej aplikacji lub metodach, ponieważ są one przeznaczone do blokowania różnych rzeczy.

Jednak, w twoim przypadku, myślę, że lepiej będzie zaglądać do Semaphore i Monitora. Nie wygląda na to, że musisz zablokować procesy, więc prawdopodobnie są lepszym rozwiązaniem w tej sytuacji.

1

Nie podałeś wystarczających informacji, aby naprawdę odpowiedzieć na to pytanie. Jak już powiedział Earwicker, Mutex pozwala na synchronizację pomiędzy procesami. Jeśli masz dwa wystąpienia tej samej aplikacji, możesz serializować dostęp. Możesz to zrobić na przykład podczas korzystania z zasobów zewnętrznych.

Teraz blokujesz na stronie chroni witrynę przed dostępem innych wątków w tym samym procesie. Może to być nieistotne w zależności od tego, co robią inne metody/wątki. Teraz, jeśli jest to jedyne miejsce, w którym ta witryna jest zablokowana, tak, tak, myślę, że to przesada.

2

Jak zauważyli inni, Mutex blokuje procesy, a lokalna blokada (Monitor) blokuje tylko wątki będące własnością bieżącego procesu. Jednak ...

Kod, który pokazałeś ma całkiem poważny błąd.Wygląda na to, że zwalniasz Mutex bezwarunkowo na końcu (tj. reconnectMutex.ReleaseMutex()), ale Mutex jest nabywany tylko wtedy, gdy site.ContainsKey() zwraca true.

Więc jeśli site.ContainsKey wróci false, zwolnienie Mutex będzie rzutować ApplicationException, ponieważ wywołujący wątek nie jest właścicielem Mutex.

+0

Dzięki - znalazłem ten błąd po tym, jak to opublikowałem. Nie mogłem się domyślić, dlaczego aplikacja właśnie się zamyka - to był problem. –

Powiązane problemy