2014-12-20 12 views
5

Attualmente sto leggendo l'e-book Threading in C# di Joe Albahari e, a volte nel suo codice di esempio, utilizza i blocchi in luoghi in cui non vedo alcun problema di sicurezza dei thread. Here, ad esempio, si blocca attorno alla scrittura e alla lettura dal campo _status, che si riferisce a un oggetto immutabile.Perché qui vengono utilizzati i lucchetti?

Capisco che se la classe ProgressStatus erano mutabili, si avrebbe bisogno di chiudere intorno lettura e la scrittura ad esso, perché se un thread fosse pre svuotato tra l'aggiornamento dei campi percentComplete e StatusMessage da un altro thread la lettura del stato, il secondo thread potrebbe ottenere una coppia di valori non valida per quei campi. (Completamento al 100%/"Operazione in corso ...")

Ma poiché ProgressStatus è immutabile, non può verificarsi uno stato non valido. Se Joe ha rimosso entrambi i blocchi, quale problema di sicurezza dei thread potrebbe verificarsi?

risposta

4

Se Joe ha rimosso entrambi i blocchi, quale problema di sicurezza dei thread potrebbe verificarsi?

Potrebbe portare a "dati obsoleti", il codice di lettura potrebbe memorizzarlo nella cache e visualizzare solo un vecchio valore.

Questo utilizzo di lock è un tipico, sta beneficiando di un effetto collaterale di lock: ha una barriera di memoria implicita e impedisce di visualizzare una copia precedente. Si vedrebbe più comunemente un volatile ProgressStatus _status; ma volatile ha anche i suoi problemi.

Hai ragione che le effettive operazioni di lettura e scrittura non richiedono realmente un blocco qui (l'acquisizione di un riferimento è atomico).

+0

Grazie - Ho il sospetto che un campo volatile potrebbe fare il trucco. "' volatile' ha anche i suoi problemi "- puoi per favore elaborare? – dgmulf

4

I lettori potrebbero non vedere mai l'aggiornamento _status ad un nuovo valore, ad esempio. Tutte le letture potrebbero essere compresse in una lettura fisica.

Inoltre, penso che potresti vedere oggetti parzialmente inizializzati nel caso in cui _status sia stato eseguito il commit sulla memoria prima dei campi nell'oggetto a cui si fa riferimento.

Si noti che questo blocco non ha nulla a che fare con l'oggetto a cui si fa riferimento. Si tratta di proteggere il riferimento stesso.

Accedere a una variabile su più thread quando uno degli accessi è una scrittura è una corsa di dati. Ogni genere di cose può accadere. Quello che ho detto sopra sono solo esempi.

+0

Grazie. Tuttavia, mi sembra che entrambi i problemi che menzioni possano essere risolti in modo più espressivo usando un campo "volatile" o barriere della memoria. Correggimi se sbaglio. – dgmulf

+1

Sì, possono essere risolti usando volatile ma è più difficile da capire. Le primitive complicate dovrebbero essere usate se i requisiti di prestazione lo richiedono. – usr

+1

Un problema con l'uso di barriere di memoria in questo caso specifico è che significherebbe usare qualcosa nella parte 2 dell'articolo che non è spiegato fino alla parte 4. –

Problemi correlati