Gibt es einen Vorteil der Verwendung des volatilen Keywords im Gegensatz dazu, die unterblockte Klasse zu verwenden?

StackOverflow https://stackoverflow.com/questions/1701216

Frage

Mit anderen Worten, kann ich etwas mit einer flüchtigen Variablen tun, die nicht auch mit einer normalen Variablen und der ineinandergreifenden Klasse gelöst werden konnte?

War es hilfreich?

Lösung

Bearbeiten: Frage weitgehend umgeschrieben

Um diese Frage zu beantworten, tauchte ich in dieser Angelegenheit etwas weiter ein und fand ein paar Dinge darüber heraus volatile und Interlocked Das war mir nicht wussten. Lassen Sie uns das nicht nur für mich klarstellen, sondern auch für diese Diskussion und andere Leute, die darüber nachlesen:

  • volatile Lesen/Schreiben sollen immun gegen neu ordnen. Dies nur bedeutet Lesen und Schreiben, es tut es nicht bedeuten jede andere Aktion;
  • Volatilität ist auf der CPU, dh und Hardware -Ebene nicht gezwungen (x86 verwendet Erwerben- und Freigabezäune auf irgendein lesen Schreiben). Es verhindert Compiler- oder CLR -Optimierungen;
  • Interlocked Verwendet Atomic -Montage -Anweisungen für Vergleichexchange (cmpxchg), Zuwachs (inc) etc;
  • Interlocked verwendet ein Schloss manchmal: a Hardware -Sperren auf Multi -Prozessor -Systemen; In Uni-Processor-Systemen gibt es keine Hardware-Sperre.
  • Interlocked unterscheidet sich von volatile In dem verwendet es a Voller Zaun, wo flüchtig einen halben Zaun verwendet.
  • Eine Lesung nach einem Schreiben kann neu angeordnet werden Wenn Sie verwenden volatile. Es kann nicht mit passieren Interlocked. VolatileRead und VolatileWrite Haben Sie das gleiche Nachbestellungsproblem wie "Volatile (Link dank Brian Gideon).

Nachdem wir die Regeln haben, können wir eine Antwort auf Ihre Frage definieren:

  • Technisch: Ja, es gibt Dinge, mit denen Sie anfangen können volatile Das können Sie nicht mit dem Interlocked:
    1. Syntax: Sie können nicht schreiben a = b wo a oder b ist volatil, aber das ist offensichtlich;
    2. Sie können einen anderen Wert lesen, nachdem Sie ihn aufgrund der Neuordnung in eine volatile Variable geschrieben haben. Sie können dies nicht mit tun Interlocked. Mit anderen Worten: Sie können sein weniger sicher mit volatile dann kannst du mit sein mit sein Interlocked.
    3. Leistung: volatile ist dann schneller Interlocked.
  • Semantisch: Nein, weil Interlocked Bietet lediglich ein Superset von Operationen und ist sicherer zu bedienen, da es volles Fechten angewendet wird. Sie können nichts mit tun volatile Das können Sie nicht mit dem Interlocked Und du kannst es tun viel mit Interlocked Dass du nicht mit volatilem ausmachen kannst:

    static volatile int x = 0;
    x++;                        // non-atomic
    static int y = 0;
    Interlocked.Increment(y);   // atomic
    
  • Umfang: Ja, eine Variable deklarieren volatile macht es für jeden einzelnen Zugang volatil. Es ist unmöglich, dieses Verhalten auf andere Weise zu erzwingen, daher volatile kann nicht ersetzt werden durch Interlocked. Dies ist in Szenarien erforderlich, in denen andere Bibliotheken, Schnittstellen oder Hardware auf Ihre Variable zugreifen und sie jederzeit aktualisieren oder die neueste Version benötigen.

Wenn Sie mich fragen würden, ist dieses letzte Stück das eigentliche echte Bedarf an volatile und kann es ideal machen, wenn zwei Prozesse den Speicher teilen und ohne Sperren lesen oder schreiben müssen. Deklaration einer Variablen als volatile ist in diesem Zusammenhang viel sicherer und zwingt alle Programmierer zur Verwendung Interlocked (was Sie durch den Compiler nicht erzwingen können).


Bearbeiten: Das folgende Zitat war Teil meiner ursprünglichen Antwort, ich werde es in ;-) belassen ;-)

Ein Zitat vom der C# Programmiersprache Standard:

Für nichtflüchtige Felder können Optimierungstechniken, die berücksichtigen, dass Nachbestellungsanweisungen zu unerwarteten und unvorhersehbaren Ergebnissen führen können, in Multithread -Programmen, die auf Felder zugreifen Schlossdatement. Diese Optimierungen können vom Compiler, vom Laufzeitsystem oder durch Hardware durchgeführt werden. Für volatile Felder sind solche Neubestehenungsoptimierungen eingeschränkt:

  • Eine Lektüre eines flüchtigen Feldes wird a genannt flüchtige Lektüre. Eine volatile Lektüre hat: Semantik erwerben "; dh es wird garantiert vor allen Verweise auf Speicher auftreten, die danach in der Anweisungssequenz auftreten.

  • Ein Schreiben eines flüchtigen Feldes wird a genannt volatiles Schreiben. Ein volatiles Schreiben hat "Release -Semantik"; Das heißt, es wird garantiert nach jedem Speicherreferenzen vor der Schreibanweisung in der Anweisungssequenz geschieht.

Aktualisieren: Frage hat weitgehend umgeschrieben, meine ursprüngliche Antwort korrigiert und eine "echte" Antwort hinzugefügt

Andere Tipps

Dies ist ein ziemlich komplexes Thema. Ich finde Joseph Albahari's Schreiben Um eine der endgültigen und genaueren Quellen für Multithreading -Konzepte im .NET -Framework zu sein, die dazu beitragen könnten, Ihre Frage zu beantworten.

Um schnell zusammenzufassen, gibt es viel Überlappung zwischen den volatile Schlüsselwort und das Interlocked Klasse so weit sie verwendet werden können. Und natürlich gehen beide weit über das hinaus, was Sie mit einer normalen Variablen tun können.

Ja - Sie können den Wert direkt betrachten.

Solange Sie nur die unterblockte Klasse verwenden, um auf die Variable zuzugreifen, gibt es keinen Unterschied. Was flüchtig Tut ist dem Compiler mitteilt, dass die Variable etwas Besonderes ist und bei der Optimierung nicht davon ausgehen sollte, dass sich der Wert nicht geändert hat.

Nimmt diese Schleife:

bool done = false;

...

while(!done)
{
... do stuff which the compiler can prove doesn't touch done...
}

Wenn Sie einstellen done zu true In einem anderen Thread würden Sie erwarten, dass die Schleife beendet. Wenn jedoch - wenn getan ist, ist nicht markiert als als volatile Dann hat der Compiler die Möglichkeit zu erkennen, dass sich der Schleifencode nie ändern kann done und es kann den Vergleich für den Ausgang optimieren.

Dies ist eines der schwierigen Dinge an der Multithread -Programmierung - viele der Situationen, die Probleme sind, treten nur in bestimmten Situationen auf.

Ich werde nicht versuchen, eine Autorität zu diesem Thema zu sein, aber ich würde Ihnen wärmstens empfehlen, sich einen Blick darauf zu werfen Dieser Artikel durch den gepriesenen Jon Skeet.

Schauen Sie sich auch den letzten Teil von an Diese Antwort Welche Details was volatile sollte verwendet werden für.

Ja, Sie können eine gewisse Leistung erzielen, indem Sie eine volatile Variable anstelle eines Schlosses verwenden.

Lock ist eine vollständige Speicherbarriere, die Ihnen die gleichen Eigenschaften einer flüchtigen Variablen sowie vielen anderen verleihen kann. Wie bereits erwähnt, stellt volatil nur sicher, dass in Multi-Thread-Szenarien, wenn eine CPU einen Wert in seiner Cache-Linie ändert, der andere CPUs den Wert sofort sieht, jedoch keine Semantikverriegelung sicherstellt.

Die Sache ist Lock ist viel leistungsfähiger als flüchtig und Sie sollten volatil verwenden, um unnötige Schlösser zu vermeiden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top