2012-03-30 13 views
16

Ostatnio widziałem tego kodu na stronie internetowej, i moje pytanie jest następujące:Blokowanie pojedynczej zmiennej binarnej podczas wielowątkowości?

 private bool mbTestFinished = false; 

     private bool IsFinished() 
     { 
      lock(mLock) 
      { 
       return mbTestFinished; 
      } 
     } 

     internal void SetFinished() 
     { 
      lock(mLock) 
      { 
       mbTestFinished = true; 
      } 
     } 

W środowisku wielowątkowym, jest to naprawdę konieczne, aby zablokować dostęp do mbTestFinished?

+6

Jest to najbardziej sprawdzalny mechanizm zapewniający, że nie jest to odczyt w pamięci podręcznej CPU (który nie działałby dobrze między wątkami) - 'volatile' też by działało, ale z powodów zbyt skomplikowanych (to nie jest * zamiar * "lotnego", ale raczej: efekt uboczny) –

+4

@MarcGravell Zawsze myślałem, że jest intencją 'volatile'; Czy przypadkiem nie zrzucisz dobrego linku, który wyjaśnia, co to jest? –

+1

@romkyns: Ta [odpowiedź] (http://stackoverflow.com/a/4103879/158779) zapewnia pewien wgląd. –

Odpowiedz

9

Tak, jest potrzebna. W środowisku .Net stosowane są pewne optymalizacje, a czasami, gdy często odwiedzane jest miejsce w pamięci, dane są przenoszone do rejestrów procesora. Tak więc, w tym przypadku, jeśli mbTestFinished jest w rejestrze procesora, wtedy odczytujący go wątek może otrzymać błędną wartość. Zatem dzięki użyciu klucza ulotnego wszystkie wejścia do tej zmiennej są wykonywane w miejscu pamięci, a nie w rejestrach. Z drugiej strony, nie mam pojęcia o częstotliwości tego zdarzenia. Może to wystąpić z bardzo małą częstotliwością.

9

Moim zdaniem nie, blokada jest zbędny tu z dwóch powodów:

  1. zmienne logiczne nie może spowodować przypisanie łzawienie jak long na przykład, stąd nie ma potrzeby blokowania.
  2. Aby rozwiązać problem z widocznością, wystarczy tylko volatile. Prawdą jest, że lock wprowadza domyślne ogrodzenie, ale ponieważ lock nie jest wymagany dla atomowości, wystarcza volatile.
+0

To prawda, zakładając, że przedstawiony kod jest jedyną * rzeczą używającą blokady. Jeśli istnieją inne miejsca, w których 'mLock' jest brany, konwersja na' volatile' może spowodować błędy. –

+0

@romkyns: Tak, zakładam, że jest to niezależny scenariusz. – Tudor

4

Jeśli MLOCK jest TYLKO zmiennej mbTestFinished, to jest to trochę overkill. Zamiast tego można użyć kombinacji: volatile lub Interlocked, ponieważ oba są konstruktami trybu użytkownika dla synchronizacji wątków. zablokować (lub monitora) jest hybrydowe Konstrukt w tym sensie, że jest on również zoptymalizowane w celu uniknięcia przejeżdżających z/do trybu jądra miarę możliwości. Książka "CLR przez C#" ma dogłębną dyskusję nad tymi pojęciami.