Warum brauche ich eine Speicherbarriere?
C # 4 in Kürze (übrigens sehr zu empfehlen) verwendet den folgenden Code, um das Konzept von MemoryBarrier zu demonstrieren (vorausgesetzt, A und B wurden auf verschiedenen Threads ausgeführt):
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 Barrieren 1 & 4 dieses Beispiel daran hindern, 0 zu schreiben, und Barrieren 2 & 3 ein @ lieferFrischgarantie: Sie stellen sicher, dass, wenn B nach A lief, @ gelesen wi_Komplet würde auswerten zuwah.
Ich verstehe es nicht wirklich. Ich denke, ich verstehe, warum Barrieren 1 und 4 notwendig sind: Wir wollen nicht, dass wir an @ schreibe_Antworte muss optimiert und nach dem Schreiben an @ platziert werd_Komplet (Barriere 1) und wir müssen sicherstellen, dass_Antworte wird nicht zwischengespeichert (Barriere 4). Ich denke auch, ich verstehe, warum Barrier 3 notwendig ist: Wenn A lief, bis kurz nach dem Schreiben von_complete = true, B müsste noch aktualisiert werden_Komplet, um den richtigen Wert zu lesen.
Ich verstehe aber nicht, warum wir Barrier 2 brauchen! Ein Teil von mir sagt, dass es daran liegt, dass Thread 2 (mit B) bereits lief, bis (aber nicht mit)if (_complete) und so müssen wir versichern, dass_Komplet wird aktualisiert.
Allerdings sehe ich nicht, wie das hilft. Ist es nicht immer noch möglich, dass_Komplet wird in A auf true gesetzt, aber bei der B-Methode wird eine zwischengespeicherte (falsche) Version von @ angezei_Komplet? Dh, wenn Thread 2 Methode B bis nach dem ersten MemoryBarrier und dann Thread 1 Methode A bis @ ausgeführt h_complete = true aber nicht weiter, und dann Thread 1 fortgesetzt und getestetif (_complete) - könnte daswen nicht zu @ führfalsc?