2016-11-05 11 views
5

To jest coś, czego nigdy nie zrozumiałem. To wydaje się prawie jak hack stworzyć fikcyjny obiekt, który pobiera lock ed, jak npDlaczego musimy zablokować i obiekt w C#?

class Account 
{ 
    decimal balance; 
    private Object thisLock = new Object(); 

    public void Withdraw(decimal amount) 
    { 
     lock (thisLock) 
     { 
      if (amount > balance) 
      { 
       throw new Exception("Insufficient funds"); 
      } 
      balance -= amount; 
     } 
    } 
} 

z https://msdn.microsoft.com/en-us/library/c5kehkcz.aspx.

Dlaczego nie projektanci językowe sprawiają, że tak, że

class Account 
{ 
    decimal balance; 

    public void Withdraw(decimal amount) 
    { 
     lock 
     { 
      if (amount > balance) 
      { 
       throw new Exception("Insufficient funds"); 
      } 
      balance -= amount; 
     } 
    } 
} 

byłoby równoważne?

+5

@ Sayse Wcale nie, w przeciwnym razie nikt nie zrozumie, jak używać 'blokady' w pierwszej kolejności. Powody, dla których trzeba podać parametr "lock", muszą być jasne, a pytanie jest bardzo ważne, jeśli autor nie rozumie tych powodów. – rucamzu

+0

@rucamzu - Myślę, że źle odczytałem pytanie – Sayse

Odpowiedz

7

Instancja przekazana do lock służy do zidentyfikowania sekcji krytycznej.

W kodzie może znajdować się dowolna liczba niepowiązanych sekcji krytycznych, a każda z nich będzie blokować inny obiekt. Nieparametryczna instrukcja lock, podobna do tej, którą sugerujesz, nie byłaby w stanie odróżnić wielu krytycznych sekcji.

EDIT

Chociaż może to wydawać się oczywiste, warto zauważyć, że każda pojedyncza część potrzeby wprowadzania danej sekcji krytycznej musi mieć dostęp do zablokowanego obiektu. Nie chodzi więc o tworzenie arbitralnej instancji tuż przed i w tym samym zakresie niż instrukcja lock.

+0

Tak, masz rację, źle odczytałem i myślę, że nie rozumie, co robi blokada. Dzięki za komentarz – mybirthname

+0

@mojbirthname Bez problemu. I tylko dla przypomnienia, moje wyjaśnienia były jasne i użyteczne. – rucamzu

0

Myślę, że zamieszanie leży w tym, co robi słowo kluczowe blokady. Nie mówiąc tylko 1 wątek może wejść na ten fragment kodu, ale to mówi 2 rzeczy:

  1. tylko jeden wątek może wprowadzić ten fragment kodu, który ma thisLock
  2. Wszelkie inne części, która jest zablokowana z thisLock jest również nie może być dopuszczony do wpisania przez wątek z wyjątkiem tego wątku, ponieważ ten wątek ma tę blokadę.

To, co sugerujesz, dotyczy tylko pierwszego, ale nie obu. Spójrz na ten przykład:

class Account 
{ 
    decimal balance; 
    private Object thisLock = new Object(); 
    private Object thisLock2 = new Object(); 

    public void Withdraw(decimal amount) 
    { 
     lock (thisLock) 
     { 
      if (amount > balance) 
      { 
       throw new Exception("Insufficient funds"); 
      } 
      balance -= amount; 
     } 

     // more code here but no locking necessary... 

     lock(thisLock) 
     { 
      // only one thread can enter here who has thisLock 
     } 

     lock (thisLock2) 
     { 
      // If T1 (thread1) is working with thisLock, T2 can come here since it has nothing to do 
      // with thisLock. 
     } 
    } 

    public void AnotherOperation() 
    { 
     lock (thisLock) 
     { 
      // code here... 
     } 
    } 

    public void YetAnotherOperation() 
    { 
     lock (thisLock) 
     { 
      // code here... 
     } 
    } 
} 

Kiedy nitki, powiedzmy T1, robi część wypłaty z pierwszej blokady, wszystkie inne sekcje klasy z zamkiem (thisLock) są niedozwolone wpisu za pomocą każdego innego wątku, jak również . Jednak część z thisLock2 może być wprowadzona przez inne wątki.

Najlepszym sposobem na myślenie o słowie kluczowym blokady, przynajmniej pomogło mi, gdy uczyłem się, było pojmowanie go jako zakładnika. Innymi słowy, kiedy niektóre części kodu są wykonywane, w twoim przykładzie trzeba wziąć zakładnika (thisLock). Kiedy więc ten Lock zostanie wzięty jako zakładnik, żaden inny wątek nie może wziąć go jako zakładnika, dopóki ten wątek nie uwolni zakładnika. Dlatego wszystkie inne sekcje kodu, które również potrzebują tego samego zakładnika, stają się niedostępne.

Powiązane problemy