Penso che la maggior parte delle persone sono a conoscenza del problema seguente che avviene quando si costruisce in modalità di rilascio (codice preso dal Threading in C#):stranezza Volatile
static void Main()
{
bool complete = false;
var t = new Thread (() =>
{
bool toggle = false;
while (!complete) toggle = !toggle;
});
t.Start();
Thread.Sleep (1000);
complete = true;
t.Join(); // Blocks indefinitely
}
a causa di ottimizzazioni del compilatore cache il valore della complete
e impedendo così il bambino thread da mai vedere il valore aggiornato.
Tuttavia, cambiando il codice di sopra di un bit:
class Wrapper
{
public bool Complete { get; set; }
}
class Test
{
Wrapper wrapper = new Wrapper();
static void Main()
{
var test = new Test();
var t = new Thread(() =>
{
bool toggle = false;
while (!test.wrapper.Complete) toggle = !toggle;
});
t.Start();
Thread.Sleep(1000);
test.wrapper.Complete = true;
t.Join(); // Blocks indefinitely
}
}
rende il problema andare via (cioè il filo bambino è in grado di uscire dopo 1 secondo) senza l'uso di volatile
, recinzioni memoria, o qualsiasi altra meccanismo che introduce una recinzione implicita.
In che modo l'incapsulamento aggiunto dell'indicatore di completamento influenza la sua visibilità tra i thread?
Il tuo codice non è garantito per funzionare, ma non è garantito il fallimento. Non si deve fare affidamento sull'ottimizzazione del compilatore per la correttezza (o l'inesattezza in questo caso). – svick
@svick: non lo sono davvero. Era solo qualcosa che ho notato accidentalmente. – Tudor
possibile duplicato di [Un esempio riproducibile di utilizzo volatile] (http://stackoverflow.com/questions/6164466/a-reproducable-example-of-volatile-usage) –