Frage

Lassen Sie sich sagen, ich habe eine Struktur bekommt, die aus 100 Bytes bestehen. Welche Garantien habe ich zu folgendem Code?

m_myLargeStruct = someValue; // copying 100 bytes
Thread.MemoryBarrier();

// Executed by another thread, after "Thread.MemoryBarrier" was called by the first thread
Console.WriteLine(m_myLargeStruct.ToString());

Hat das Speichermodell Garantie, dass das 100 Bytes kopiert wird abgeschlossen sein, nach der Platzierung der Speicherbarriere? oder Sie Speicherbarrieren gelten nur für Typen, die auf die Größe der Architektur des Prozessors sind? (4 Bytes für 32-Bit- und 8 Bytes zu 64 Bit).
Ist dies der Grund, warum die flüchtig Schlüsselwort nur für primitive Typen gilt? (Wenn ich ein 8-Byte-Mitglied als flüchtiges erklären, bedeutet dies, dass ein verriegelter instrinct verwendet werden, den Wert zu ändern? [Da Unteilbarkeit nicht für Typen größer als 4 Bytes auf 32-Bit-Maschinen garantiert]).

Ich hoffe, ich war klar genug .. :)
Dank

War es hilfreich?

Lösung

Offensichtlich ist die Antwort Nein , oder besser gesagt, haben Sie keine Garantie über alles. Nichts hindert das Betriebssystem von dem Thread auslagern, die vor dem Start den Thread zu der 100-Byte-Struktur schreiben, die Drucke aus der 100-Byte-Struktur.

Eine Speicherbarriere verwendet wird, wenn Sie den Zugriff auf Daten, die durch eine Flagge oder ein anderes Atom-Wert koordinieren wollen. Ich weiß nicht, was genau Sie versuchen, dies zu tun, ich nicht, dass Ihnen guten Beispiel-Code geben, wie Sie es tun sollen.

Andere Tipps

Wenn der Lese Thread eine Speicherbarriere zu hat, weiß ich nicht denken es wird Ihnen viel helfen.

Persönlich würde ich schrecken vor:

  • Structs, die so groß
  • Erste tief in das Speichermodell zu Schreibsperre freier Code

... wenn Sie einen wirklich wichtigen Grund haben, dies zu tun. Es ist sehr groß Festschleusenfreies Codierung direkt mit veränderbaren Daten zu erhalten; Ich glaube, dass selbst die Experten Kampf. Normalerweise finde ich, dass die „eine Sperre nehmen für jeden Block aus den Zugriff auf die Daten“ -Ansatz einfacher ist, richtig zu machen und ist in Ordnung in Bezug auf die Leistung für 99% der Fälle.

Ich vertraue auf Microsoft das PFX Team zu bekommen schleusenfreien rechten Codierung und für sie mir Wege WTH I zu erhalten, ihren Code verwenden können, mein eigenes Schloss kostenlose Programme relativ einfach zu schreiben. Ich traue mich nicht, diese Art der Sache richtig zu machen. Wenn ich jemals explizit benötigen eine Speicherbarriere zu verwenden, das bedeutet wahrscheinlich, dass ich versuchen zu hart.

Sie müssen eine andere Speicherbarriere im zweiten Thread, bevor Console.WriteLine. (Wenn Ihr System asymmetrische Speicherbarrieren bietet, es ist genug, um eine Release-Barriere nach der Abtretung und einer Acquire Barriere vor Console.WriteLine auszuführen).

Datengröße spielt keine Rolle.

Sie benötigen eine Speichersperre in beiden Orten / Threads, und natürlich müssen Sie irgendeine Art von Synchronisation zwischen den beiden so der Barriere des zweiten Thread nicht ‚run‘, bevor der erste Thread.

Insbesondere wird der Schreib Thread benötigt eine ‚release‘ Speicherbarriere, und der Lesefaden braucht eine ‚acquire‘ Speicherbarriere (wenn die zugrunde liegende Plattform, um die separate Barriere Semantik unterstützt).

Es sei denn, Sie fragen akademische Neugier oder Sie Ihren eigenen Rahmen zu schreiben, sollten Sie wirklich verwenden nur ein Synchronisationsobjekt aus der Bibliothek / Rahmen / Plattform. all dieses Zeug ist richtig schwierig zu bekommen versucht, und es ist bereits in den dafür vorgesehenen Synchronisations Objekte gemacht.

Nun, zunächst einmal sollten Sie nicht eine Struktur haben, die so groß ist. Es sei denn, Sie extrem vorsichtig sind, wie Sie die Struktur verwenden, wird es langsamer sein als eine Klasse. Außerdem ist es kontraintuitiv den Wert Semantik von Strukturen.

sagte, wird die Speicherbarriere garantieren, dass die Struktur kopiert wird. Die Optimierung wird keine Anweisungen über die Barriere bewegen.

Das Schlüsselwort volatile ist ein bisschen anders. Es garantiert, dass keine Operationen gegen die variable weg optimiert ist, und es macht die Reihenfolge der Speicherzugriffe zu gewährleisten. Doch für die Datentypen, die nicht atomar zugegriffen werden kann, ist es meist nutzlos für Threading Zwecke, wie Sie noch die Hälfte einen neuen Wert und die Hälfte eines alten Wert lesen kann.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top