C# 4 in Kürze (stark btw empfohlen) Der folgende Code verwendet das Konzept des Memory (vorausgesetzt, dass A und B auf unterschiedlichen Fäden wurden ausgeführt) zu demonstrieren:Warum brauche ich eine Speicherbarriere?
class Foo{
int _answer;
bool complete;
void A(){
_answer = 123;
Thread.MemoryBarrier(); // Barrier 1
_complete = true;
Thread.MemoryBarrier(); // Barrier 2
}
void B(){
Thread.MemoryBarrier(); // Barrier 3;
if(_complete){
Thread.MemoryBarrier(); // Barrier 4;
Console.WriteLine(_answer);
}
}
}
sie erwähnen, dass Barriers 1 & 4 dies verhindern Beispiel vom Schreiben 0 und Barrieren 2 & 3 bietet eine Frische Garantie: sie sorgen dafür, dass, wenn B lief nach A, Lesen _COMPLETE zu wahren bewerten würde.
Ich bekomme es nicht wirklich. Ich glaube, ich verstehe, warum Barrieren 1 & 4 sind notwendig: Wir wollen nicht auf die Schreiben auf _answer optimiert und nach dem Schreiben auf _COMPLETE (Barrier 1), und wir müssen dafür sorgen, platziert werden, dass _answer ist nicht zwischengespeichert (Barriere 4). Ich glaube auch, dass ich verstehe, warum Barrier 3 notwendig ist: Wenn A bis _complete = true ausgeführt wurde, müsste B noch _complete aktualisieren, um den richtigen Wert zu lesen.
Ich verstehe nicht, obwohl wir Barrier 2 brauchen! Ein Teil von mir sagt, dass es vielleicht daran liegt, dass Thread 2 (läuft B) bereits lief (aber nicht inklusive) wenn (_complete) und so müssen wir sicherstellen, dass _complete aktualisiert wird.
Allerdings sehe ich nicht, wie das hilft. Ist es nicht immer möglich, dass _complete in A auf True gesetzt wird, aber die B-Methode eine gecachete (falsche) Version von _complete? Dh wenn Thread 2 Verfahren B lief bis nach dem ersten Memory und dann Thread 1 Verfahren A bis _COMPLETE = true lief, aber nicht weiter, und dann wieder aufgenommen Gewinde 1 und getestet if (_COMPLETE) - könnte, dass, wenn nicht false?
Warum sollte jemand dies über "volatile" verwenden? – ChaosPandion
@Chaos: CLR über C# Buch (Richter) hat eine großartige Erklärung - IIRC ist, dass 'flüchtig' bedeutet, dass alle Zugriffe auf die Var als flüchtig behandelt werden und volle Speicherbarrieren in beiden Richtungen erzwingen. Das ist oft viel perfekter als nötig, wenn Sie stattdessen nur eine Lese- oder eine Schreibbarriere benötigen und nur bestimmte Zugriffe. –
@Chaos: nicht wirklich der Punkt, aber ein Grund ist, dass volatile hat seine eigenen Macken in Bezug auf Compiler-Optimierungen, die zu Deadlock führen können, siehe http://www.bluebytesoftware.com/blog/2009/02/24/TheMagicalDuelingDeadlockingSpinLocks .aspx – hackerhasid