2009-10-23 13 views
10

W mojej aplikacji wielowątkowej używam niektórych zmiennych, które mogą być zmieniane przez wiele instancji w tym samym czasie. To dziwne, ale sprawdziło się bez problemu. Ale oczywiście muszę sprawić, by był bezpieczny dla wątków. Właśnie zaczynam od blokad, więc będę aprobować twoją radę:Blokowanie właściwości, dobre podejście?

Kiedy klient łączy się, klasa Klient jest tworzona, gdy każdy Klient ma swoją własną zmienną "A".

Czasami klient wywołuje metodę tak:

Client selectedClient SelectOtherClientClassByID(sentID); 

selectedClient.A=5; 

żadnych problemów do tej pory z tym, nawet gdy 5 klas robili w tym samym czasie (pula wątków), ale myślałem, co na temat dodawania zamki do A właściwościach ?

odczuwalna:

A { 
    get { return mA; } 
    set { 
     // use lock here for settting A to some value 
    }  
} 

byłoby OK?

Odpowiedz

16

Musisz używać zamków w OBU get i set. Ta blokada musi być tym samym obiektem. Na przykład:

private object mylock = new object(); 

public int A { 

    get { 
    int result; 
    lock(mylock) { 
    result = mA; 
    } 
    return result; 
    } 

    set { 
    lock(mylock) { 
     mA = value; 
    } 
    } 
} 
+1

Dziękuję ... btw za przeczytanie to dlatego, że mogło to ulec zmianie podczas czytania przez inną klasę? – Petr

+1

Nie jest dobrym pomysłem zablokowanie tego, ponieważ jest dostępny z zewnątrz typu. –

+0

Może ulec zmianie podczas ustawiania. Blokada działa jak bariera, uniemożliwiając jakiekolwiek inne działanie, dopóki właściciel blokady nie zwolni blokady. –

2

To bardzo rzadkie, gdy wystarczy ustawić tylko jedną nieruchomość. Częściej selectedClient.A = 5 będzie częścią znacznie większej operacji logicznej, która obejmuje kilka przydziałów/ocen/etc. Podczas tej całej operacji wolisz, aby selectedClient był w stanie spójnym i nie wprowadzał zakleszczeń/warunków wyścigu. W związku z tym, to będzie dużo lepiej narazić SyncRoot nieruchomość w swojej klasie Client i blokady, że z kodu wywołującego:

Client selectedClient = GetClient(...); 

lock(selectedClient.SyncRoot) 
{ 
    selectedClient.A = 5; 
    selectedClient.B = selectedClient.A * 54; 
} 
+0

Nie mam żadnych innych zmiennych, które dzielą się niż jedna lista i te int. Głównie nic nie wiem o SyncRoot :) – Petr

+0

SyncRoot nie jest zalecany: Zobacz http://blogs.msdn.com/brada/archive/2003/09/28/50391.aspx –

+0

@_NT: Cytując z posta na blogu: "Zapewniamy, że nie popełnimy tego samego błędu, ponieważ tworzymy ogólne wersje tych kolekcji."I oto jesteśmy, 6 lat później, z Listą .SyncRoot bez żadnych zniechęcających notatek w MSDN: http://msdn.microsoft.com/en-us/library/bb356596.aspx –

6

Blokowanie dostępu do właściwości wewnątrz od dostępowych może prowadzić do fałszywych wyników. Dla przykładu, spójrz na następujący kod:

class C { 
    private object mylock = new object(); 

    public int A { 

     get { 
     int result; 
     lock(mylock) { 
     result = mA; 
     } 
     return result; 
     } 

     set { 
     lock(mylock) { 
      mA = value; 
     } 
     } 
    } 
} 
C obj = new C; 
C.A++; 

(tak, mam skopiowane go od pierwszej odpowiedzi) Jest wyścigu tutaj! Operacja "C.A ++" w rzeczywistości wymaga dwóch oddzielnych wejść do A, jeden do uzyskania wartości, a drugi do ustawienia zaktualizowanej wartości. Nic nie gwarantuje, że te dwa wejścia będą realizowane razem bez przełączania kontekstu między nimi. Klasyczny scenariusz warunków wyścigu!

Tak, uwaga! Nie jest dobrym pomysłem umieszczanie blokad wewnątrz akcesorów, zamki powinny być jawnie uzyskane, jak sugeruje poprzednia odpowiedź (chociaż nie musi to być z SyncRoots, dowolny obiekt zrobi)

+0

Masz na myśli również ręcznie dodać obiekt blokady do wszystkich połączeń w kodzie? Wydaje mi się, że istnieje co najmniej 20 odczytów i 15 zapisów w moim kodeksie do tej pory – Petr

+0

Aby to zrobić, rozszerz swój zamek tak, aby obejmował cały krytyczny region. t do A ++. –

+0

NT: Nie rozumiem cię prawdopodobnie. Mam około 15 metod z różnymi operacjami z tą zmienną na różnych instancjach.Nie jestem pewny, jak masz na myśli rozszerzenie loc k. Więc blokada właściwości nie jest dobra, jeśli przeczytałem poprawnie wszystko powyżej – Petr

Powiązane problemy