Das Schlüsselwort volatile
in C# dreht sich alles um Lesen/Schreiben Neuordnung, also ist es etwas ziemlich esoterisch.
http://www.albahari.com/threading/part4.aspx#_Memory_Barriers_and_Volatility
(das halte ich über Einfädeln eines der „Bibeln“ sein) schreibt:
Das Schlüsselwort volatile den Compiler weist einen Belegungs-Zaun auf jedem aus diesem Feld lesen zu erzeugen und einen Freigabefaktor bei jedem Schreiben in dieses Feld.Ein Acquire-Fence verhindert, dass andere Lese-/Schreibvorgänge vor dem Zaun verschoben werden; Ein Freigabezaun verhindert, dass andere Lese-/Schreibvorgänge nach dem Zaun verschoben werden. Diese "Halbzäune" sind schneller als Vollzäune, weil sie der Laufzeit und der Hardware mehr Spielraum für Optimierungen geben.
Es ist etwas ganz unlesbar :-)
Jetzt ... Was es bedeutet nicht:
- Es bedeutet nicht, dass ein Wert wird jetzt/gelesen werden wird geschrieben werden jetzt
es bedeutet einfach, dass, wenn Sie etwas von einem flüchtigen Variable lesen, alles el se, die gelesen/geschrieben wurde, bevor dieser "spezielle" Lesevorgang nach diesem "speziellen" Lesevorgang verschoben wird. Es schafft also eine Barriere. Paradoxerweise garantieren Sie beim Lesen einer volatilen Variablen, dass alle Schreibvorgänge, die Sie mit einer anderen Variablen (flüchtig oder nicht) zum Zeitpunkt des Lesens gemacht haben, ausgeführt werden.
Ein flüchtiges Schreiben ist wahrscheinlich etwas wichtiger und wird zum Teil von der Intel-CPU garantiert, und etwas, das von der ersten Version von Java nicht garantiert wurde: keine Neuordnung des Schreibvorgangs. Das Problem war:
object myrefthatissharedwithotherthreads = new MyClass(5);
wo
class MyClass
{
public int Value;
MyClass(int value)
{
Value = value;
}
}
Nun ..., dass die Expression vorstellen kann sein:
var temp = new MyClass();
temp.Value = 5;
myrefthatissharedwithotherthreads = temp;
wo temp
etwas vom Compiler generiert wird, dass man‘ t sehen.
Wenn die Schreibvorgänge neu angeordnet werden können, könnten Sie haben:
var temp = new MyClass();
myrefthatissharedwithotherthreads = temp;
temp.Value = 5;
und ein anderer Thread eine teilweise initialisiert sehen konnte MyClass
, da der Wert von myrefthatissharedwithotherthreads
lesbar ist, bevor die Klasse MyClass
Initialisierung beendet ist.
'volatile' verhindert das Neuanordnen von Befehlen um den Variablenzugriff. Es ist ziemlich komplex. Siehe http://www.albahari.com/threading/part4.aspx#_Memory_Barriers_and_Volatility – xanatos
[Eric Lipperts Antwort auf eine andere Frage] (http://Stackoverflow.com/a/26315297/517852) hat eigentlich eine sehr gute Beschreibung des Unterschiede in der Semantik von flüchtigen zwischen C++ und C#. –