Gibt es einen Vorteil der Verwendung des volatilen Keywords im Gegensatz dazu, die unterblockte Klasse zu verwenden?
-
19-09-2019 - |
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?
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 vonvolatile
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 passierenInterlocked
.VolatileRead
undVolatileWrite
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 demInterlocked
:- Syntax: Sie können nicht schreiben
a = b
woa
oderb
ist volatil, aber das ist offensichtlich; - 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 mitvolatile
dann kannst du mit sein mit seinInterlocked
. - Leistung:
volatile
ist dann schnellerInterlocked
.
- Syntax: Sie können nicht schreiben
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 tunvolatile
Das können Sie nicht mit demInterlocked
Und du kannst es tun viel mitInterlocked
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, dahervolatile
kann nicht ersetzt werden durchInterlocked
. 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.