Basierend auf meinem Verständnis ein C # Array gegeben, der Akt der gleichzeitig von mehreren Threads über das Array Iterieren ist ein Thread einen sicheren Betrieb.
Mit Iteration über das Array meine ich das Lesen aller Positionen innerhalb des Arrays mittels einer einfachen alten for
Schleife . Jeder Thread liest einfach den Inhalt eines Speicherplatzes innerhalb des Arrays. Niemand schreibt etwas, sodass alle Threads auf konsistente Weise dasselbe lesen.
Dies ist ein Stück Code, der das tut, was ich oben geschrieben habe:
public class UselessService
{
private static readonly string[] Names = new [] { "bob", "alice" };
public List<int> DoSomethingUseless()
{
var temp = new List<int>();
for (int i = 0; i < Names.Length; i++)
{
temp.Add(Names[i].Length * 2);
}
return temp;
}
}
Mein Verständnis ist also, dass die Methode DoSomethingUseless
threadsicher ist und dass es nicht erforderlich ist , die string[]
durch einen threadsicheren Typ zu ersetzen (wie ImmutableArray<string>
zum Beispiel).
Hab ich recht ?
Nehmen wir nun an, wir haben eine Instanz von IEnumerable<T>
. Wir wissen nicht, was das zugrunde liegende Objekt ist, wir wissen nur, dass ein Objekt implementiert ist IEnumerable<T>
, sodass wir es mithilfe der foreach
Schleife durchlaufen können .
Nach meinem Verständnis gibt es in diesem Szenario keine Garantie dafür, dass das gleichzeitige Durchlaufen dieses Objekts von mehreren Threads eine threadsichere Operation ist. Anders ausgedrückt, es ist durchaus möglich, dass das gleichzeitige Durchlaufen der IEnumerable<T>
Instanz von verschiedenen Threads den internen Status des Objekts unterbricht, sodass es beschädigt wird.
Bin ich in diesem Punkt richtig?
Was ist mit der IEnumerable<T>
Implementierung der Array
Klasse? Ist es threadsicher?
Anders ausgedrückt, ist der folgende Code-Thread sicher? (Dies ist genau der gleiche Code wie oben, aber jetzt wird das Array durch Verwendung einer foreach
Schleife anstelle einer for
Schleife iteriert. )
public class UselessService
{
private static readonly string[] Names = new [] { "bob", "alice" };
public List<int> DoSomethingUseless()
{
var temp = new List<int>();
foreach (var name in Names)
{
temp.Add(name.Length * 2);
}
return temp;
}
}
Gibt es eine Referenz, die angibt, welche IEnumerable<T>
Implementierungen in der .NET-Basisklassenbibliothek tatsächlich threadsicher sind?
Array
) ist threadsicher, solange alle Threads es nur lesen. Gleiches List<T>
gilt für und wahrscheinlich für jede andere von Microsoft geschriebene Sammlung. Es ist jedoch möglich, eigene zu erstellen IEnumerable
, die nicht threadsichere Dinge im Enumerator ausführen. Daher ist es keine Garantie dafür, dass alles, was implementiert IEnumerable
wird, threadsicher ist.
foreach
funktioniert mit mehr als nur Enumeratoren. Der Compiler ist intelligent genug, um zu wissen, dass er bei statischen Typinformationen, die darauf hinweisen, dass es sich bei der Auflistung um ein Array handelt, die Generierung des Enumerators überspringt und direkt auf das Array zugreift, als wäre es eine for
Schleife. Wenn die Sammlung eine benutzerdefinierte Implementierung von unterstützt GetEnumerator
, wird diese Implementierung ebenfalls verwendet, anstatt sie aufzurufen IEnumerable.GetEnumerator
. Die Vorstellung, dass foreach
nur Menschenhandel stattfindet, IEnumerable/IEnumerator
ist falsch.
volatile
garantiert nicht, dass Sie die aktuellste Aktualisierung einer Variablen erhalten, da C # es verschiedenen Threads ermöglicht, unterschiedliche Lese- und Schreibreihenfolgen zu beobachten, und daher der Begriff "frischeste" nicht global definiert ist . Anstatt über Frische nachzudenken, sollten Sie darüber nachdenken, welche Einschränkungen volatile
die Nachbestellung von Schreibvorgängen einschränken .