Joe Albahari hat eine great series auf Multithreading, das ist ein Muss lesen und sollte auswendig für jeden bekannt sein, der C# Multithreading.Ist das 'volatile' Schlüsselwort in C# immer noch fehlerhaft?
In Teil 4 jedoch erwähnt er die Probleme mit flüchtigem:
Hinweis, dass flüchtige Anwendung nicht daran hindert, eine Schreib gefolgt von einem Lesen aus getauscht werden, und dies kann Rätsel erstellen. Joe Duffy veranschaulicht das Problem gut mit dem folgenden Beispiel: Wenn Test1 und Test2 gleichzeitig auf verschiedenen Threads ausgeführt werden, ist es möglich für a und b beide mit einem Wert von 0 (trotz der Verwendung von flüchtigen auf beide X und y)
mit einem nachgestellten Hinweis, dass die MSDN-Dokumentation falsch ist:
die Dokumentation MSDN besagt, dass die Verwendung des flüchtigen Schlüsselwort stellt sicher, dass der meist up-to-date-Wert in der Gegenwart Feld jederzeit. Das ist falsch, da, wie wir gesehen haben, ein Schreiben gefolgt von einem Lesen neu geordnet werden kann.
Ich habe überprüfte die MSDN documentation, die zuletzt im Jahr 2015 geändert wurde, aber noch aufgeführt:
Das flüchtige Schlüsselwort gibt an, dass ein Feld von mehrere Threads modifiziert werden könnte, die zur gleichen Zeit ausgeführt werden . Felder, die als flüchtig deklariert sind, unterliegen nicht Compiler-Optimierungen, die Zugriff von einem einzelnen Thread annehmen. Dies stellt sicher, dass der aktuellste Wert immer im Feld zu jeder Zeit vorhanden ist.
Im Moment habe ich noch flüchtig vermeiden zugunsten der ausführlicheren Gewinde zu verhindern, veraltete Daten verwenden:
private int foo;
private object fooLock = new object();
public int Foo {
get { lock(fooLock) return foo; }
set { lock(fooLock) foo = value; }
}
Da die Teile über Multithreading im Jahr 2011 geschrieben wurden, ist das Argument heute noch gültig? Sollten Volatilität noch immer zugunsten von Sperren oder vollen Speicherzäunen vermieden werden, um zu verhindern, dass sehr schwer zu erzeugende Fehler auftreten, die, wie erwähnt, sogar vom CPU-Anbieter abhängen, auf dem sie läuft?
Worum geht es in Ihrem Beispiel bei 'return' und Zuweisungsanweisung nach' lock'? – Yarik
Dies ist immer noch irreführend. Volatile bietet Semantiken für das Akquirieren/Freigeben von Speicher, die ausreichen, um viele Algorithmen effizient zu implementieren. Ja, es ist schwierig zu verwenden, aber das macht es nicht kaputt (die Lösung von C++ ist eindeutig überlegen, aber sie hatten den Vorteil, die Probleme mit flüchtigen in Java zu sehen) (Und jeder, der denkt, dass Speicherbarrieren einfacher als flüchtig sind) hat einfach nicht genug Erfahrung mit anderen Architekturen als x86.Versuche, Speicherbarrieren auf einer Architektur ohne Multi-Copy-Atomizität zu verwenden und zu sehen, wie weit du kommst) – Voo
(Die msdn Beschreibung ist zugegebenermaßen merklich schlechter. Offensichtlich versteht derjenige, der dieses Snippet geschrieben hat, überhaupt nicht flüchtig und man kann nur hoffen, dass es nie erlaubt wurde schreibe eine Zeile mit gleichzeitigem Code) – Voo