2014-09-24 3 views
10

Cosa succederà se due thread leggono questa proprietà allo stesso tempo?Caricamento lento senza blocchi nell'applicazione multithread

public static HugeType HugeType 
{ 
    get 
    { 
     if (tenderCache == null) 
     { 
      tenderCache = Config.Get<HugeType>("HugeType", null); 
     } 
     return tenderCache; 
    } 
} 

Il mio scopo è di sola lettura e non è fondamentale se si creano due istanze. Dovrei aggiungere serrature in ogni caso?

+0

Si noti che nei modelli di memoria più deboli rispetto al modello .NET, è possibile che altri thread vedano un riferimento 'tenderCache' non nullo, ma l'oggetto a cui fa riferimento non è ancora completamente costruito. Ad esempio questo è sicuramente un data race in C++. –

+0

'Config.Get (" HugeType ", null)' può essere richiamato più di una volta e l'ultimo thread vince. Se ciò non ti fa male, non hai bisogno di un lucchetto. –

+2

Vorrei suggerire la domanda [this] (http://stackoverflow.com/questions/6847721/when-should-i-use-lazyt). Lazy è quello che vuoi qui. –

risposta

9

Poiché non si ha sincronizzazione, è possibile chiamare il metodo di inizializzazione molte volte, probabilmente anche se altri thread hanno completato l'inizializzazione completamente (a causa della mancanza di una barriera di memoria). Se non ti interessa eseguire più volte l'operazione di inizializzazione e restituirà sempre lo stesso valore corretto indipendentemente da quante volte è stato chiamato e anche se sono state fatte più chiamate contemporaneamente, allora il codice funzionerà sicuramente, anche se non funzionerà altrettanto bene

Detto questo, verificare correttamente che l'inizializzazione avvenga solo una volta è molto facile, dato che è già un problema risolto. Puoi semplicemente memorizzare un Lazy<HugeType> nel tuo campo invece di un HugeType e Lazy si prenderà cura della sincronizzazione di inizializzazione per te.

+1

+1 Cosa succede se due thread ottengono (tenderCache == null) come true e entrambi provano e scrivono in tenderCache = Config.Get ("HugeType", null); allo stesso tempo? Oppure il primo (tenderCache == null) come true prova a leggere tenderCache mentre il secondo sta scrivendo su di esso. – Paparazzi

+1

@Blam Se entrambi provano a scrivere il valore, allora si vincerà; supponendo che l'inizializzazione crei sempre lo stesso valore, significa che non importa chi vince. Le scritture su variabili di un tipo di riferimento sono atomiche, quindi se il valore viene letto mentre un altro thread sta tentando di scriverle, la lettura avviene prima della scrittura, o la scrittura avviene prima della lettura e quelle sono le uniche opzioni. Ottenere spazzatura o "la fine del mondo" non sono possibilità. – Servy

+0

Questo è in realtà maturo per un problema di thread e quindi essere consapevoli dei problemi esistenti se avessi più linee nell'inizializzazione come aggiungere elementi ad una collezione. Le linee aggiuntive di codice all'interno del controllo NULL potrebbero essere perse a causa del fatto che il condizionale non è più vero ad es. TenderCache == null – Firegarden