C# non consente il blocco su un valore nullo. Suppongo che potrei controllare se il valore è nullo o meno prima di bloccarlo, ma poiché non l'ho bloccato, un altro thread potrebbe venire avanti e rendere il valore nullo! Come posso evitare questa condizione di gara?Perché C# non consente il blocco di un valore nullo?
risposta
Blocca un valore che non è mai nullo, ad es.
Object _lockOnMe = new Object();
Object _iMightBeNull;
public void DoSomeKungFu() {
if (_iMightBeNull == null) {
lock (_lockOnMe) {
if (_iMightBeNull == null) {
_iMightBeNull = ... whatever ...;
}
}
}
}
anche essere attenti a evitare questa condizione di gara interessante con bloccaggio doppio controllo: Memory Model Guarantees in Double-checked Locking
Potrebbe essere utile aggiungere in modo univoco all'oggetto di blocco per richiamare l'immutabilità desiderata – cordialgerm
perché il blocco _lockOnMe può impedire ad altri l'accesso a _iMightBeNull? –
-1: il tuo codice è ancora suscettibile alle condizioni della gara a cui ti sei collegato; '_iMightBeNull' deve essere dichiarato come volatile. O, preferibilmente, si dovrebbe usare 'Lazy
ci sono due problemi qui:
primo luogo, non bloccare su un oggetto null
. Non ha senso come in che modo due oggetti, entrambi null
, possono essere differenziati?
secondo luogo, per inizializzare sicurezza una variabile in un ambiente multithreading, utilizzare il modello ricontrollato bloccaggio:
if (o == null) {
lock (lockObj) {
if (o == null) {
o = new Object();
}
}
}
Questo farà sì che un altro filo non è già inizializzato l'oggetto e può essere utilizzato per attuare il Modello Singleton.
Non è possibile bloccare su un valore nullo in quanto il CLR non ha posto per fissare lo SyncBlock a, che è ciò che permette al CLR per sincronizzare l'accesso a oggetti arbitrari tramite Monitor.Enter/Exit (che è quello che usa internamente lock
)
+1: questa è la risposta più corretta. –
Perché C# non consente il blocco di un valore nullo?
Paul's answer è l'unico tecnicamente corretto finora, quindi accetterei quello. È perché i monitor in .NET utilizzano il blocco di sincronizzazione che è collegato a tutti i tipi di riferimento. Se si dispone di una variabile che è null
, non si riferisce a nessun oggetto e ciò significa che il monitor non ha accesso a un blocco di sincronizzazione utilizzabile.
Come posso evitare questa condizione di gara?
L'approccio tradizionale consiste nel bloccare un riferimento a un oggetto che non sarà mai null
. Se ti trovi in una situazione in cui questo non può essere garantito, classificherei questo approccio non tradizionale. Non c'è molto altro che posso menzionare qui a meno che non descriviate in modo più dettagliato lo scenario particolare che può portare a obiettivi di blocco nullable.
La prima parte della tua domanda ha già una risposta, ma vorrei aggiungere qualcosa per la seconda parte della tua domanda.
È più semplice utilizzare un oggetto diverso per eseguire il blocco, specialmente in questa condizione. Questo risolve anche il problema di mantenere gli stati di più oggetti condivisi in una sezione critica, ad es. elenco dei dipendenti e elenco delle foto dei dipendenti.
Inoltre questa tecnica è anche utile quando è necessario acquisire blocco sul tipi primitivi ad esempio int o decimale ecc
A mio parere se usare questa tecnica come tutti gli altri ha suggerito, allora non è necessario eseguire assegno nullo due volte. per esempio.nella risposta accettata Cris ha usato se due volte la condizione che in realtà non fa alcuna differenza perché l'oggetto bloccato è diverso da quello che viene effettivamente modificato, se si sta bloccando su un oggetto diverso allora l'esecuzione del primo controllo null è inutile e lo spreco di CPU .
Vorrei suggerire il seguente codice;
Non riesco a vedere nessuna condizione di gara qui se qualcun altro vede condizioni di gara, si prega di rispondere nei commenti. Come puoi vedere nel codice sopra, risolve 3 problemi in una volta, un controllo null richiesto prima del blocco, in secondo luogo crea una sezione critica senza bloccare due fonti condivise e il terzo blocco più di un oggetto causa deadlock a causa della mancanza di attenzione durante la scrittura codice.
Di seguito viene illustrato come utilizzare i blocchi sui tipi primitivi.
object readonly syncRootIteration = new object();
long iterationCount = 0;
long iterationTimeMs = 0;
public void IncrementIterationCount(long timeTook)
{
lock (syncRootIteration)
{
iterationCount++;
iterationTimeMs = timeTook;
}
}
public long GetIterationAvgTimeMs()
{
long result = 0;
//if read without lock the result might not be accurate
lock (syncRootIteration)
{
if (this.iterationCount > 0)
{
result = this.iterationTimeMs/this.iterationCount;
}
}
return result;
}
Felice filettatura :)
- 1. Perché istanziare variabili con un valore nullo
- 2. Errore: il valore non può essere nullo
- 3. C# struct, come assegnare un valore nullo?
- 4. Il valore cast per il tipo "Decimal" non è riuscito perché il valore materializzato è nullo
- 5. Perché il tentativo di aggiungere a un valore nullo non genera un InvalidOperationException?
- 6. Ruby controlla se il blocco è nullo
- 7. Perché l'interfaccia Set non consente elementi null?
- 8. Perché la JVM consente di impostare il valore "alto" per IntegerCache, ma non il "basso"?
- 9. Il valore MVC3 non può essere nullo. Nome parametro: valore
- 10. Perché python non consente trattini
- 11. Perché assegnare un valore alla stringa prima del confronto, quando il valore predefinito è nullo
- 12. Perché F # non consente più attributi in cui C# fa?
- 13. Non aggiornare colonna se il valore di aggiornamento è nullo
- 14. Hibernate non consente ad un oggetto incorporato con un campo int di essere nullo?
- 15. ottenere il primo valore non nullo da array PHP
- 16. Perché C# non consente const e static sulla stessa riga?
- 17. Perché strncpy non è nullo?
- 18. Come verificare il valore nullo in NSNumber
- 19. ASP.NET non può memorizzare nella cache il valore nullo
- 20. filtro valore nullo ng-repeat non visualizzazione
- 21. perché il boost di mpl set consente tipi non univoci
- 22. Verificare che un valore intero sia Nullo in C#
- 23. Perché il compilatore Java a volte consente l'annullamento del blocco di null?
- 24. MVC4 TDD - System.ArgumentNullException: il valore non può essere nullo.
- 25. Perché il compilatore consente vector.begin() = vector.end() in C++?
- 26. Differenza tra il valore di ritorno della funzione di blocco non bloccante e l'argomento $ di blocco?
- 27. Perché Task.Delay() consente un ritardo infinito?
- 28. Perché il blocco catch di questo codice non viene eseguito?
- 29. assegnando un valore nullo per un int
- 30. Perché Hashtable non consente chiavi o valori Null?
Perché non basta usare un membro che inizializzato staticamente e * sempre non è nullo * – zerkms
Da quanto ho capito, nulla è sostanzialmente nulla. Come puoi mettere un blocco su nulla? In altre parole, string myString = null dichiara una variabile di tipo string, ma questo è tutto ciò che c'è da fare - non esiste come oggetto perché non ha valore. – Tim