Quando si utilizza volatile/Thread.MemoryBarrier() per la sicurezza del thread?Quando utilizzare 'volatile' o 'Thread.MemoryBarrier()' nel codice di blocco thread-safe? (C#)
risposta
Si utilizza volatile
/Thread.MemoryBarrier()
quando si desidera accedere a una variabile attraverso thread senza bloccare.
Le variabili che sono atomiche, ad esempio int
, vengono sempre lette e scritte interamente insieme. Ciò significa che non otterrai mai metà del valore prima che un altro thread lo cambi e l'altra metà dopo che è stata modificata. Per questo puoi tranquillamente leggere e scrivere il valore in diversi thread senza syncronising.
Tuttavia, il compilatore può ottimizzare alcune letture e scritture, che vengono impedite con la parola chiave volatile
.Se ad esempio avere un ciclo come questo:
sum = 0;
foreach (int value in list) {
sum += value;
}
Il compilatore può effettivamente fare i calcoli in un registro del processore e solo scrivere il valore della variabile sum
dopo il ciclo. Se si crea la variabile sum
volatile
, il compilatore genererà il codice che legge e scrive la variabile per ogni modifica, in modo che il suo valore sia aggiornato in tutto il ciclo.
Cosa c'è di sbagliato con
private static readonly object syncObj = new object();
private static int counter;
public static int NextValue()
{
lock (syncObj)
{
return counter++;
}
}
?
Questo fa tutto il necessario blocco, barriere di memoria, ecc. Per voi. È ben compreso e più leggibile di qualsiasi codice di sincronizzazione personalizzato basato su volatile
e Thread.MemoryBarrier()
.
EDIT
non riesco a pensare ad uno scenario in cui mi piacerebbe utilizzare volatile
o Thread.MemoryBarrier()
. Ad esempio
private static volatile int counter;
public static int NextValue()
{
return counter++;
}
è non equivalente al codice sopra ed è non thread-safe (volatile
non opera ++
magicamente diventare thread-safe).
In un caso come questo:
private static volatile bool done;
void Thread1()
{
while (!done)
{
// do work
}
}
void Thread2()
{
// do work
done = true;
}
(che dovrebbe funzionare) userei un ManualResetEvent per segnalare quando Thread2 è fatto.
Niente di "sbagliato" nel codice. Sto cercando di capire le circostanze in cui si applicano volatili e MemoryBarrier. Come nella risposta di Jon Skeet qui: http://stackoverflow.com/questions/395232/we-need-to-lock-a-net-int32-when-reading-it-in-a-multithreaded-code. – Alex
.net ha anche un modello di memoria abbastanza rigido, tale lettura o scrittura non può seguire un'altra scrittura. –
Anche se le specifiche ECMA hanno un modello di memoria abbastanza debole, quindi si potrebbe voler fare attenzione, vedere http://www.bluebytesoftware.com/blog/2007/11/10/CLR20MemoryModel.aspx e http: // blog .msdn.com/cbrumme/archive/2003/05/17/51445.aspx –
In sostanza se si utilizza qualsiasi altro tipo di sincronizzazione per rendere il proprio codice non protetto, non è necessario.
La maggior parte dei meccanismi di blocco (incluso il blocco) implica automaticamente una barriera di memoria in modo che più processori possano ottenere le informazioni corrette.
Volatile e MemoryBarrier vengono principalmente utilizzati in scenari senza blocco in cui si tenta di evitare la penalizzazione delle prestazioni del blocco.
Edit: Si consiglia di leggere this article da Joe Duffy circa il modello di memoria CLR 2.0, chiarisce un sacco di cose (se siete veramente interessati vi consigliamo di leggere tutto l'articolo da Joe Duffie che è di grandi dimensioni il più esperto in parallelismo in .NET)
+1, ma solo così è assolutamente chiaro. Se fai ciò che fa dtb, volatile/Thread.MemoryBarrier non è necessario. Ci sono anche situazioni in cui la volatilità da sola su un membro non è sufficiente. – Skurmedel
Poiché il nome implica volatile garantisce che il valore della cache venga svuotato in memoria in modo che tutti i thread vedano lo stesso valore. Ad esempio, se ho un numero intero la cui ultima scrittura è salvata nella cache, altri thread potrebbero non vederlo. Potrebbero persino vedere la loro copia cache di quell'intero. Marcare una variabile come volatile lo fa leggere direttamente dalla memoria.
Sriwantha Sri Aravinda Attanayake
- 1. Volatile e Thread.MemoryBarrier in C#
- 2. Errore correlato volatile nel codice C++
- 3. Elementi di array C# volatile?
- 4. VB.NET: Devo chiamare Thread.MemoryBarrier() prima di ogni lettura se completo sempre le mie scritture con Thread.MemoryBarrier()?
- 5. Quando utilizzare volatile con memoria CUDA condivisa
- 6. Il blocco effettivo è importante quando si decide di utilizzare volatile?
- 7. Quando utilizzare il thread di blocco in C#?
- 8. Quando utilizzare Cygwin o MinGW per compilare il codice C?
- 9. quando utilizzare DIRECTORY_SEPARATOR nel codice PHP?
- 10. benchmarking, codice di riordino, volatile
- 11. Quando utilizzare una query o un codice
- 12. Codice imprevisto nel blocco sincronizzato
- 13. Come utilizzare UTF-8 nel codice C?
- 14. codice di blocco # c in modalità asincrona
- 15. variabili di multithreading volatile C++
- 16. Funzioni membro volatile C++
- 17. Utilizzare le proprietà C# nel codice C++ non gestito
- 18. Quando utilizzare blocchi di codice impliciti o espliciti
- 19. Variabile condivisa senza blocco in Swift? (funzionamento volatile)
- 20. Necessità di scrittura di array volatile mentre si è nel blocco sincronizzato
- 21. Un DAO per thread o DAO threadsafe?
- 22. java.util.concurrent.Future threadsafe?
- 23. Visual C++ Volatile
- 24. Una variabile di blocco deve essere dichiarata volatile?
- 25. Quando utilizzare C#/C++
- 26. const volatile, registrarsi volatile, statica volatili in C++
- 27. Devo usare identificatori di blocco ("end;") nel mio codice?
- 28. Il codice C libera un blocco?
- 29. Posso rendere libero il blocco di codice seguente/atomico?
- 30. Perché Thread.MemoryBarrier è utilizzato qui?
+1, ma in quali scenari è importante che il compilatore generi codice che legge e scrive la variabile per ogni modifica? – dtb
Ciò è maggiormente desiderato quando si inserisce dtb, se non un thread può ottenere un valore diverso da quello dell'altro e possono accadere tutti i tipi di cose pazzesche. – Skurmedel
Bene, quello o usare una barriera di memoria. – Skurmedel