C # Threading & Blocking

Mi chiedo quale sia l’approccio migliore per caricare i dati in modo thread-safe. Tradizionalmente, ho usato il modello a doppia serratura e questo ha funzionato abbastanza bene. Ora, con l’aggiunta del tipo System.Lazy, mi chiedo se basarsi sull’interno di Lazy e il caricamento sia migliore e fare il lavoro in un modo molto migliore. Sembra più pulito e più facile da leggere, ma è meglio?

qualche idea?

namespace SomeNameSpace { public class DataStoreContext { private readonly static Lazy context = new Lazy(() => new DataStoreContext()); private Lazy<Dictionary> _entities = new Lazy<Dictionary>(() => { return DataStoreContext.Instance.Load(); }); private readonly object _syncRoot = new object(); private DataStoreContext() { } public Dictionary Data { get { return _entities.Value; } } public static DataStoreContext Instance { get { return context.Value; } } private Dictionary Load() { // Load Data from some data store. return null; } private Dictionary LoadWithLock() { if (_entities == null) { lock (_syncRoot) { if (_entities == null) { Dictionary entities = this.Load(); _entities = entities; return _entities; } } } return _entities ; } public void Clear() { _entities = new Lazy<Dictionary>(() => { return DataStoreContext.Instance.Load(); }); } } } 

Sembra più pulito e più facile da leggere, ma è meglio?

Sì. Il blocco con doppia verifica è difficile da ottenere. Richiede una barriera di memoria per essere corretta. La tua implementazione non è in realtà garantita dal CIL *.

Per i dettagli, vedere questa voce di Wikipedia .

Usando Lazy , ottieni un codice che non è solo più pulito, ma che è effettivamente corretto su tutte le piattaforms.

* Si noti che questo probabilmente funziona perfettamente su x86 e x64, eseguendo il runtime Microsoft, a causa del modello di memoria della piattaforma. Tuttavia, non è garantito che le specifiche siano corrette senza adeguate barriere di memoria.

Per la documentazione di MSDN:

Per impostazione predefinita, tutti i membri pubblici e protetti della class Lazy sono thread-safe e possono essere utilizzati contemporaneamente da più thread. Queste garanzie sulla sicurezza dei thread possono essere rimosse facoltativamente e per istanza, utilizzando parametri per i costruttori del tipo.

È abbastanza sicuro per le operazioni di lettura e scrittura. Pertanto, direi che rimani con questo perché è molto più pulito.

Ma, come afferma la documentazione, è ansible distriggersre la sicurezza del thread con alcuni parametri opzionali per il costruttore.