Ich habe mich bei volatile
für den Referenztyp verwirrt.
Ich verstehe, dass für den primitiven Typ volatile
Wertänderungen von einem anderen Thread sofort widerspiegeln kann. Als Referenztyp kann er die Adressänderungen sofort widerspiegeln. Wie steht es aber mit dem Inhalt des Objekts? Sind sie noch zwischengespeichert?
(Angenommen List.Add()
ist eine atomare Operation)
Zum Beispiel habe ich:
%Vor% Wenn ein Thread die Funktion AddValue
aufruft, ändert sich die Adresse der Liste nicht, wird ein anderer Thread über die "Inhalts" -Wechsel der Liste aktualisiert, oder der Inhalt kann für jeden Thread zwischengespeichert werden und tut dies nicht Update für andere Threads?
Ich verstehe, dass flüchtige Werte für primitive Typen Wertänderungen von einem anderen Thread sofort widerspiegeln können
Sie verstehen auf mindestens drei Arten falsch. Sie sollten nicht versuchen, volatile zu verwenden, bis Sie alles über schwache Speichermodelle verstehen, Semantiken erwerben und freigeben und wie sie Ihr Programm beeinflussen.
Zunächst sollte klar sein, dass sich volatile Auswirkungen auf Variablen und nicht auf Werte auswirken.
Zweitens hat volatile keine Auswirkungen auf Variablen, die Werte von Werttypen enthalten, anders als auf Variablen, die Referenzen enthalten.
Drittens bedeutet volatil nicht, dass Wertänderungen von anderen Threads sofort sichtbar sind . Flüchtig bedeutet, dass Variablen Semantik erwerben und freigeben haben. Volatile beeinflusst die Reihenfolge, in der die Nebenwirkungen von Gedächtnismutationen in einem bestimmten Thread beobachtet werden können . Die Vorstellung, dass es eine konsistente universelle Reihenfolge von Mutationen gibt und dass diese Mutationen in dieser Reihenfolge augenblicklich von allen Threads beobachtet werden können, ist keine durch das Speichermodell gewährleistete Garantie.
Was ist jedoch mit dem Inhalt des Objekts?
Was ist damit? Der Speicherort, auf den eine flüchtige Variable vom Referenztyp verweist, muss keine besonderen Threading-Eigenschaften aufweisen.
Wenn ein Thread die Funktion AddValue aufruft, ändert sich die Adresse der Liste nicht, wird ein anderer Thread über die "Inhalts" -Wechsel der Liste aktualisiert.
Nein. Warum sollte es? Dieser andere Thread befindet sich möglicherweise auf einem anderen Prozessor, und dieser Prozessorcache hat möglicherweise die Seite mit der Adresse des Arrays geladen, das die Liste unterstützt. Das Mutieren der Liste hat möglicherweise den Speicherort geändert, der die Adresse des Arrays enthält, um auf einen vollständig anderen Speicherort zu verweisen.
Natürlich ist die Listenklasse gar nicht threadsafe. Wenn Sie den Zugriff auf die Liste nicht sperren, kann die Liste einfach abstürzen und absterben, wenn Sie dies versuchen.
Sie brauchen nicht flüchtig; Sie müssen Thread-Sperren um Zugriffe auf die Liste setzen. Da Gewindesperren volle Zäune induzieren, sollten Sie keine Halbzäune von volatile verwenden.
Es ist schlimmer als das.
Wenn Sie gleichzeitig auf ein Objekt zugreifen, das nicht threadsicher ist, stürzt Ihr Programm möglicherweise ab. Veraltete Informationen sind nicht das schlechteste mögliche Ergebnis.
Wenn Sie .NET-Basisklassenbibliotheksobjekte zwischen Threads freigeben, haben Sie wirklich keine andere Wahl, als Sperren zu verwenden. Für die Lockless-Programmierung benötigen Sie invasive Änderungen an Ihren Datenstrukturen auf den niedrigsten Ebenen.
Das Schlüsselwort volatile
hat keine Auswirkungen auf den Inhalt der Liste (genauer gesagt, auf das Objekt, auf das verwiesen wird).
Wenn Sie über aktualisiert / nicht aktualisiert für einen anderen Thread sprechen, wird dies zu stark vereinfacht. Sie sollten die lock
-Anweisung verwenden, um den Zugriff auf die freigegebene Liste zu synchronisieren. Ansonsten sind Sie effektiv mit Rennbedingungen konfrontiert, die zum Programmabsturz führen können. Die Klasse List<T>
ist nicht threadsicher.
Sehen Sie sich Ссылка an, um eine gute Erklärung dafür zu erhalten, was Flüchtige tatsächlich tun und wie sie Felder beeinflussen.
Der ganze Teil des Threads auf dieser Seite ist sowieso ein Muss, er enthält eine Menge nützlicher Informationen, die sich für mich beim Entwerfen von Multithread-Software als sehr nützlich erwiesen haben.