Mögliches Duplikat:
Synchronisierung der Threads. Wie genau macht Sperren den Zugriff auf den Speicher "korrekt"?
Diese Frage ist inspiriert von diese.
Wir haben folgende Testklasse
class Test
{
private static object ms_Lock=new object();
private static int ms_Sum = 0;
public static void Main ()
{
Parallel.Invoke(HalfJob, HalfJob);
Console.WriteLine(ms_Sum);
Console.ReadLine();
}
private static void HalfJob()
{
for (int i = 0; i < 50000000; i++) {
lock(ms_Lock) { }// empty lock
ms_Sum += 1;
}
}
}
Das tatsächliche Ergebnis liegt sehr nahe am erwarteten Wert 100 000 000 (50 000 000 x 2, da 2 Schleifen gleichzeitig laufen), mit einer Differenz von etwa 600 - 200 (der Fehler beträgt auf meinem Rechner ca. 0,0004 %, was sehr gering ist). Keine andere Art der Synchronisierung kann eine derartige Annäherung bieten (entweder ist der Fehlerprozentsatz viel größer oder er ist 100% korrekt).
Wir gehen derzeit davon aus, dass dieses Maß an Genauigkeit darauf zurückzuführen ist, dass das Programm auf folgende Weise läuft:
Die Zeit läuft von links nach rechts, und 2 Threads werden durch zwei Zeilen dargestellt.
wobei
-
Die Blackbox steht für den Prozess des Erfassens, Haltens und Freigebens der
-
Sperre plus steht für Additionsoperation ( Schema steht für Skalierung auf meinem PC, Sperren dauert schätzungsweise 20 Mal länger als Addieren)
-
Das weiße Kästchen stellt den Zeitraum dar, in dem versucht wird, eine Sperre zu erreichen, und dem weiteren Warten auf die Verfügbarkeit der Sperre
Außerdem bietet das Schloss einen vollständigen Speicherschutz.
Die Frage ist nun: Wenn das obige Schema das darstellt, was vor sich geht, was ist dann die Ursache für einen so großen Fehler (jetzt sieht das Schema mit der großen Ursache wie ein sehr starkes Syncrhonisierungsschema aus)? Wir könnten den Unterschied zwischen 1-10 an den Grenzen verstehen, aber das ist eindeutig nicht der einzige Grund für den Fehler? Wir können nicht sehen, wann Schreibvorgänge in ms_Sum gleichzeitig stattfinden können, um den Fehler zu verursachen.
EDIT。 Viele Menschen ziehen gerne vorschnelle Schlüsse. Ich weiß, was Synchronisation ist, und das obige Konstrukt ist kein echter oder annähernd guter Weg, um Threads zu synchronisieren, wenn wir ein korrektes Ergebnis benötigen. Haben Sie etwas Vertrauen in den Poster oder lesen Sie vielleicht zuerst die verlinkte Antwort. Ich brauche keine Möglichkeit, 2 Threads zu synchronisieren, um Additionen parallel durchzuführen, ich erforsche diese extravagante und dennoch effiziente Methode, verglichen mit jede möglich und ungefähre alternativ, Synchronisationskonstrukt (es synchronisiert bis zu einem gewissen Grad, so dass seine nicht bedeutungslos wie vorgeschlagen)