2010-11-05 11 views

Antwort

28

verweise ich Sie auf Abschnitt 10.5.3 der Spezifikation, in dem es heißt:

Für nichtflüchtigen Felder, Optimierung Techniken, die Anweisungen neu ordnen, um unerwartete und zu unvorhersehbaren Ergebnissen in multi- führen kann Thread-Programme, die auf Felder ohne Synchronisierung wie zugreifen, die von der Lock-Anweisung (§8.12) zur Verfügung gestellt werden. Diese Optimierungen können vom Compiler, vom Laufzeitsystem oder von der Hardware ausgeführt werden.Für flüchtige Bereiche, wie zum Neuordnen Optimierungen beschränkt sind:

A Lese eines flüchtigen Feldes wird eine flüchtige Lese genannt. Ein flüchtiger Lesevorgang hat "Semantik erwerben"; das heißt, es ist garantiert, vor jeder Verweise auf Speicher auftreten, die nach in der Anweisungsfolge auftreten.

Ein Schreiben von einem flüchtigen Feld heißt flüchtige schreiben. Ein flüchtiger Schreibvorgang hat "release semantics"; das heißt, es ist garantiert, nach jedem Speicher Referenzen vor dem Schreiben Anweisung in der Anweisung Sequenz passieren.

Diese Einschränkungen gewährleisten , dass alle Fäden von einem anderen Thread in der Reihenfolge, in der sie waren durchgeführt durchgeführt flüchtigen schreibt beobachten wird. Eine konforme Implementierung ist nicht erforderlich, um eine einzige Gesamtordnung der flüchtigen Schreibvorgänge als aus allen Threads der Ausführung gesehen.

dass extrem sorgfältig lesen, wenn Sie die Absicht haben jemals ein flüchtiges Feld zu machen. Wenn Sie nicht vollständig und gründlich alle Auswirkungen der volatilen Semantik verstehen, dann versuchen Sie nicht, sie zu verwenden. Es ist normalerweise viel besser, eine Sperre zu verwenden, die Ihnen automatisch ausreichende Speicherbarrieren bietet, um die erforderliche Semantik zum Akquirieren und Freigeben zu gewährleisten. Denken Sie daran, Schlösser sind nur dann wirklich teuer, wenn sie behauptet werden.

+2

gut, das war so eine großartige Erklärung. (Y) –

+0

@Shimmy: Sie sind perfekt in der Lage, die Spezifikation ohne meine Hilfe zu finden. –

+0

Aber nicht Spezifikation 10.5.3 :) – Shimmy

4

MSDN wird zusammenfassen besser als ich ....

„Das flüchtige Schlüsselwort gibt an, dass ein Feld möglicherweise von mehreren Threads modifiziert werden, die zur gleichen Zeit ausgeführt werden. Die Felder, die volatilen deklariert werden unterliegen nicht Compiler-Optimierungen, die den Zugriff durch einen einzelnen Thread voraussetzen. Dadurch wird sichergestellt, dass immer der aktuellste Wert im Feld vorhanden ist. "

http://msdn.microsoft.com/en-us/library/x13ttww7(v=VS.100).aspx

7

Flüchtige wird für eine Variable verwendet, die ohne Ihre Aktion ändern kann, während der Code ausgeführt wird. Es weist den Compiler an, die Assembly so zu schreiben, dass die Variable nicht zwischengespeichert wird, sondern dass sie vor jeder Verwendung gelesen werden muss.

Ein Beispiel für etwas, das volatil wäre, wäre ein Hardwareregister, das in Ihrem Code gespeichert ist und liest, um festzustellen, wann ein Flag gesetzt ist. Die Hardware kann den Wert festlegen, während der Code ausgeführt wird, und ohne das flüchtige Schlüsselwort würden Sie diese Änderung nicht bemerken, da die Assembly den Wert niemals tatsächlich überprüfen würde.

6

Volatile ist ein Hinweis für den Compiler (und ngen/JIT-Compiler), dass der Wert dieser Variablen sich jederzeit ändern kann, und somit Optimierungen rund um die Variable zugreift, indem der Wert lokal volatile Cachen deaktiviert .

Betrachten wir den folgenden Code:

If (UserName == "") 
    // do something 
If (UserName == "Fred") 
    // do something 

Wenn flüchtige nicht vorhanden war, könnte der Compiler IL erzeugen, wo sie die Referenz auf dem Stapel für den ersten Vergleich speichert und als Wiederverwendungsmöglichkeiten für die zweite. Das Hinzufügen von volatile teilt dem Compiler jedoch mit, dass die Referenz möglicherweise von einem anderen Thread geändert wird, wodurch er gezwungen wird, eine IL zu generieren, die die Stack-Kopie nicht aus dem ersten Vergleich wiederverwendet.

+0

hmm, Sie meinen, jedes Mal, wenn Variable zugegriffen wird, wird es neues IL generieren, anstatt die Stapelkopie zu verwenden, richtig? –

+0

Ja, wenn flüchtig vorhanden ist, generiert der Compiler neue IL-Anweisungen, um den Feldwert für jeden Feldzugriff abzurufen. Wenn volatile nicht vorhanden ist, überspringt der Erzwungene diese IL für den zweiten und nachfolgenden gefüllten Zugriff. –

+0

Es ist erwähnenswert, dass dies nur bei Multi-Thread-Anwendungen erforderlich ist. Ein Thread liest möglicherweise UserName, dann wechselt die CPU zum anderen Thread, aktualisiert UserName, und die CPU wechselt zurück. Der erste Thread hat jetzt eine alte Version von UserName, es sei denn, es überprüft es erneut. –

2

Es ist nichts anderes als zu sagen Compiler, dass diese Variable seinen Wert durch nichts und Compiler jederzeit sollten keine Annahme über diese Variable machen ändern wird.

Normalerweise nimmt der Compiler an, dass eine Variable während der Laufzeit konstant ist. Dies kann zu Fehlern bei der wiederholten Überprüfung eines Registrierwerts führen. Weil der Registerwert durch irgendwas geändert werden kann. Also für diese Art von Variablen sollte "volatile" deklariert werden und es jedes Mal überprüft werden erscheint im Code ohne irgendeine Annahme.