2009-10-23 9 views
10

Nella mia applicazione multithreading sto usando alcune variabili che possono essere modificate da molte istanze nello stesso tempo. È strano ma ha funzionato bene senza alcun problema..ma ovviamente ho bisogno di renderlo thread-safe. Sto solo cominciando con le serrature quindi consiglioi il tuo consiglio:Blocco di proprietà, buon approccio?

Quando il client si connette, viene creato il client di classe in cui ogni client ha la propria variabile "A".

A volte, client chiama il metodo del genere:

Client selectedClient SelectOtherClientClassByID(sentID); 

selectedClient.A=5; 

Nessun problema fino ad ora con che anche quando 5 classi stavano facendo al tempo stesso (threadpool), ma stavo pensando che dire di aggiungere blocchi per A Proprietà ?

come:

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

sarebbe OK?

risposta

16

È necessario utilizzare i blocchi in ENTRAMBI ottenere e impostare. Questo blocco deve essere lo stesso oggetto. Ad esempio:

private object mylock = new object(); 

public int A { 

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

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

Grazie ... per la lettura è perché potrebbe essere cambiato durante la lettura da un'altra classe? – Petr

+1

Non è consigliabile bloccarlo perché è accessibile dall'esterno. –

+0

Potrebbe cambiare mentre stai impostando. La serratura funge da barriera, impedendo qualsiasi altra azione fino a quando il proprietario del lucchetto non rilascia il lucchetto. –

2

È molto raro quando tutto ciò che serve è impostare solo una proprietà. Più spesso, selectedClient.A = 5 farà parte di un'operazione logica molto più grande, che comporta diversi incarichi/valutazioni/ecc. Durante l'intera operazione preferiresti preferire che lo selectedClient sia in uno stato coerente e non introdurre condizioni di gara/deadlock. Pertanto, sarà molto meglio per esporre SyncRoot proprietà nella classe Client e blocco su che dal codice chiamante:

Client selectedClient = GetClient(...); 

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

Non ho altre variabili che condividono di una lista e quelle int. Principalmente, non so ancora nulla su SyncRoot :) – Petr

+0

SyncRoot non è consigliato: vedere http://blogs.msdn.com/brada/archive/2003/09/28/50391.aspx –

+0

@_NT: Citando dal post del blog: "Siate certi che non faremo lo stesso errore mentre costruiamo le versioni generiche di queste raccolte."Ed eccoci qui, 6 anni dopo, con l'elenco . SincroRoot senza note scoraggianti nel MSDN: http://msdn.microsoft.com/en-us/library/bb356596.aspx –

6

bloccando l'accesso alle proprietà all'interno di funzioni di accesso può portare a risultati falsi. Per l'esempio, osservare il seguente codice:

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++; 

(sì, ho copiato dalla prima risposta) C'è una condizione di competizione qui! L'operazione "C.A ++" richiede in realtà due accessi separati ad A, uno per ottenere il valore e l'altro per impostare il valore aggiornato. Niente garantisce che questi due accessi vengano eseguiti insieme senza che il contesto passi tra di essi. Scenario classico per condizioni di gara!

Quindi, attenzione! Non è una buona idea mettere i lucchetti dentro gli accessor, i lock dovrebbero essere esplicitamente ottenuti, come suggerisce la risposta precedente (anche se non deve essere con SyncRoots, qualsiasi oggetto lo farà)

+0

Intendi anche aggiungere manualmente un oggetto di blocco a tutte le chiamate nel codice? Suppongo che ci siano almeno 20 letture e 15 scritti sul mio codice fino ad ora – Petr

+0

Per fare ciò espandi il tuo lucchetto per coprire l'intera area critica. t do A ++. –

+0

NT: Non ti capisco bene probabilmente Ho circa 15 metodi con diverse operazioni con quella variabile su istanze diverse. Non sono sicuro di come intendevi espandere la posizione K. Quindi il blocco delle proprietà non va bene se ho letto correttamente tutto sopra – Petr

Problemi correlati