2013-02-11 14 views
12

Biorąc pod uwagę następujące klasy:Niezbędne obiekty wielokrotnej blokady?

class x 
{ 
    Object lockOne = new Object(); 
    Object lockTwo = new Object(); 

    List<Something> listOne = new List<Something>(); 
    List<Something> listTwo = new List<Something>(); 

    void MethodOne() 
    { 
     lock(lockOne) 
     { 
      // some operation on listOne 
     } 
    } 

    void MethodTwo() 
    { 
     lock(lockTwo) 
     { 
      // some operation on listTwo 
     } 
    } 
} 

Czy to prawidłowe użycie dwóch obiektów blokujące Zakładając, że MethodOne() i MethodTwo() mogą być wywoływane z różnych wątków jednocześnie zauważając, że listOne i listTwo nie są związane w żaden sposób. Jedyne operacje związane z zamkami są określone w komentarzach powyżej.

+1

nazywany jest blokada łupania i jest dobrym sposobem na zmniejszenie rywalizacji, jeśli dwa obiekty i metody są niezależny. – assylias

+0

To powinno być nazywane zdrowym rozsądkiem, robienie tego na odwrót jest bardzo złą praktyką. – Dariusz

+0

Jedną z rzeczy, na które warto zwrócić uwagę, jest użycie [ReaderWriterLock] (http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx). Jeśli czytasz tylko z listy, to pozwala na użycie wielu wątków jednocześnie ("Lista" ma odczyty bezpiecznych wątków), gdy musisz napisać, zaktualizuj blokadę i wtedy tylko jeden wątek może pisać, a wszyscy czytelnicy są zablokowani, później wielu czytelników może zacząć od nowa. –

Odpowiedz

7

Tak, jest prawidłowa. Pozwala to uniknąć niepotrzebnego blokowania jednej listy tylko dlatego, że trwają prace nad drugą listą.

+2

Prawidłowe? Tak. Rozrzutny? Tak, nie ma tu potrzeby oddzielnych obiektów blokujących. – svick

+4

Aby wyjaśnić, co powiedział svick, nie mówi on, aby zablokować pojedynczy obiekt blokady, ale [nie używał w ogóle żadnych obiektów blokujących] (http://stackoverflow.com/a/14814386/80274) i zablokować samą listę . –

6

Nie ma tutaj potrzeby oddzielnych obiektów blokujących. Poniższy kod będzie działać tak samo dobrze, z mniej kodu, mniejszym obciążeniu i mniejsze szanse na pomyłkę przy użyciu nieprawidłowej Lock:

class x 
{ 
    List<Something> listOne = new List<Something>(); 
    List<Something> listTwo = new List<Something>(); 

    void MethodOne() 
    { 
     lock (listOne) 
     { 
      // some operation on listOne 
     } 
    } 

    void MethodTwo() 
    { 
     lock (listTwo) 
     { 
      // some operation on listTwo 
     } 
    } 
} 
+10

Podobnie jak uwaga, najlepszą praktyką (jak to pokazuje) jest blokowanie tylko przedmiotów, które są "prywatne" dla klasy - w przeciwnym razie nie wiesz, co kod zewnętrzny może próbować zablokować, kiedy i powodują zakleszczenia lub warunki wyścigu . –