Wann sollte Lock vs. MemoryBarrier in .NET verwendet werden?
-
18-09-2019 - |
Frage
In .NET die lock
Schlüsselwort ist syntaktischer Zucker Monitor.Enter
Und Monitor.Exit
, man könnte also sagen, dass dieser Code
lock(locker)
{
// Do something
}
ist das gleiche wie
Monitor.Enter(locker);
try
{
// Do Something
}
finally
{
Monitor.Exit(locker);
}
Das .NET-Framework enthält jedoch auch das MemoryBarrier
Klasse, die auf ähnliche Weise funktioniert
Thread.MemoryBarrier();
//Do something
Thread.MemoryBarrier();
Ich bin verwirrt, wann ich es verwenden möchte Thread.MemoryBarrier
über dem lock
/Monitor
Ausführung?Ich bin dadurch noch verwirrter ein Threading-Tutorial welche Staaten sie auf die gleiche Weise funktionieren.
Soweit ich sehen kann, besteht der sichtbare Unterschied darin, dass kein Sperrobjekt erforderlich ist, was meiner Meinung nach der Fall ist Monitor
Sie könnten etwas über Threads hinweg tun, wo MemoryBarrier
befindet sich in einem einzelnen Thread.
Mein Bauchgefühl sagt mir, dass es einen weiteren wichtigen Unterschied gibt MemoryBarrier
gilt nur für Variablen und nicht für Methoden.
Schließlich hat dies nichts mit der bestehenden Frage zu tun Wann sollte „volatile“ oder „Thread.MemoryBarrier()“ im threadsicheren Sperrcode verwendet werden?(C#), denn das konzentriert sich auf die volatile
Schlüsselwort, dessen Verwendung ich verstehe.
Lösung
Meiner Meinung nach sollte man das fast tun niemals verwenden Thread.MemoryBarrier
.Dies wird verwendet für sperrfrei Code – stellt sicher, dass an einem Thread vorgenommene Änderungen für einen anderen Thread sichtbar sind, ohne dass die Kosten einer Sperre anfallen.Es tut nicht Im Gegensatz dazu steuern Sie die Thread-Synchronisation lock
.Ich verstehe nicht, wo in Joes Tutorial er das sagt MemoryBarrier
„Funktioniert genauso“ wie lock
.Könnten Sie erklären, woher genau Sie diesen Eindruck haben?
Meiner Ansicht nach ist Code ohne Sperren auf niedriger Ebene für fast jeden außer Entwicklern, deren Hauptkompetenz die Parallelität ist, zu schwierig.Wenn ich sperrfreien Code schreiben möchte, verwende ich Bausteine höherer Ebene gebaut von diesen Entwicklern (z. B. Parallel Extensions in .NET 4.0), anstatt zu versuchen, meine eigenen zu rollen.
Um nur ein Beispiel zu nennen: Mir wurden vor kurzem die Augen für die genaue Bedeutung von geöffnet volatile
welche ist nicht „Immer aus dem Hauptspeicher lesen, immer direkt in den Hauptspeicher schreiben“.(Mein eigenes Threading-Tutorial enthält diese Erklärung im Moment noch – etwas, das ich irgendwann korrigieren muss.) Es ist viel subtiler.Das bedeutet, dass manche meiner früheren Verwendungen von volatile
kann durchaus falsch sein.