2012-07-17 2 views
19

Ho la seguente dichiarazione di blocco:Una variabile di blocco deve essere dichiarata volatile?

private readonly object ownerLock_ = new object(); 

lock (ownerLock_) 
{ 
} 

Dovrei usare volatile parola chiave per la mia variabile di blocco?

private readonly volatile object ownerLock_ = new object(); 

su MSDN ho visto che di solito utilizzato per un campo a cui si accede senza bloccare, quindi se io uso di blocco non ho bisogno di usare volatili?

Da MSDN:

Il modificatore volatile è solitamente utilizzato per un campo a cui si accede da più thread senza utilizzare l'istruzione lock per serializzare accesso.

+0

Abbiamo bisogno di molto più contesto di questo per rispondere alla domanda. Dove si trova questo blocco in relazione agli oggetti che utilizzano il lucchetto? –

+3

È sicuramente thread-safe così com'è attualmente. Nessuna garanzia sarà possibile quando aggiungi il codice all'interno del blocco lock {}. –

+0

Non dovresti aver bisogno di bloccare un oggetto 'readonly' ... in quanto è' readonly' ... – NominSim

risposta

18

Se sei solo sempre accedere ai dati che il blocco "guardie", mentre si possiede il blocco, allora sì - rendendo tali campi volatile è superfluo. Non è necessario rendere variabile la variabile ownerLock_. (Non hai attualmente mostrato alcun codice all'interno della dichiarazione lock, il che rende difficile parlare in termini concreti - ma suppongo che tu sia effettivamente leggendo/modificando alcuni dati all'interno della dichiarazione lock.)

volatile deve essere molto utilizzato raramente nel codice dell'applicazione. Se si desidera l'accesso senza vincoli a una singola variabile, è quasi sempre più semplice ragionare su Interlocked. Se si desidera accedere senza bloccare oltre a questo, vorrei quasi sempre iniziare il blocco. (Oppure cerca di utilizzare strutture di dati immutabili per iniziare.)

Mi aspetto solo di vedere volatile all'interno del codice che sta tentando di creare astrazioni di livello superiore per il threading, ad esempio all'interno del codice TPL, ad esempio. È davvero uno strumento per gli esperti che in realtà capiscono a fondo il modello di memoria .NET ... di cui ce ne sono pochissimi, IMO.

+0

Grazie per la tua risposta veloce, diciamo che sto usando solo Lock, sembra raro, ma possono 2 thread che verranno all'istruzione lock controlleranno lo stato ownerLock_ allo stesso tempo e cercheranno di bloccarlo o viceversa? Sto facendo questa domanda perché ho avuto problemi con il blocco nel mio codice e penso che sia correlato a questo problema. –

+0

@DorCohen: solo uno di questi acquisirà il blocco alla volta. Quindi eseguirà il corpo dell'istruzione 'lock', e quando rilascerà il lock, l'altro thread sarà in grado di acquisire il lock ed eseguire il codice. –

+0

@DorCohen, sembra che il tuo problema non sia quello che stai bloccando, ma quello che stai tentando di fare all'interno del corpo del lucchetto. –

2

Se qualcosa è readonly è thread-safe, punto. (Bene, quasi. Un esperto potrebbe essere in grado di capire come ottenere una NullReferenceException sulla tua istruzione lock, ma non sarebbe facile.) Con readonly non hai bisogno di volatile, Interlocked, o di blocco. È la parola chiave ideale per il multi-threading e dovresti usarlo dove puoi. Funziona perfettamente per un oggetto di blocco in cui il suo grande svantaggio (non è possibile modificare il valore) non ha importanza.

Inoltre, anche se il riferimento è immutabile, l'oggetto a cui si fa riferimento potrebbe non esserlo. "new object()" è qui, ma se fosse un List o qualcos'altro mutabile - e non thread-safe - si si desidera bloccare il riferimento (e tutti gli altri riferimenti ad esso, se presenti) per mantenere l'oggetto da cambiare in due thread contemporaneamente.