Sind C # -Arrays threadsicher?

Bestimmtes

  1. Erstellen Sie eine function, um ein Array und einen Index als Parameter zu verwenden.
  2. Erstellen Sie ein Element-Array.
  3. Erstellen Sie eine Zählschleife.
  4. Innerhalb der Schleife eines neuen Threads weisen Sie dem Array mit dem übergebenen Indexer eine neue Instanz des Objekts zu.

Ich weiß, wie man die Threads usw. verwaltet. Ich bin daran interessiert zu wissen, ob dies Thread-sichere Art ist, etwas zu tun.

class Program { // bogus object class SomeObject { private int value1; private int value2; public SomeObject(int value1, int value2) { this.value1 = value1; this.value2 = value2; } } static void Main(string[] args) { var s = new SomeObject[10]; var threads = Environment.ProcessorCount - 1; var stp = new SmartThreadPool(1000, threads, threads); for (var i = 0; i < 10; i++) { stp.QueueWorkItem(CreateElement, s, i); } } static void CreateElement(SomeObject[] s, int index) { s[index] = new SomeObject(index, 2); } } 

Solutions Collecting From Web of "Sind C # -Arrays threadsicher?"

Ich glaube, wenn jeder Thread nur an einem separaten Teil des Arrays funktioniert, wird alles gut. Wenn Sie Daten austauschen (dh zwischen Threads kommunizieren), benötigen Sie eine Art Speicherbarriere, um Speichermodellprobleme zu vermeiden.

Ich glaube , wenn Sie einen Haufen von Threads spawnen, von denen jeder seinen eigenen Abschnitt des Arrays Thread.Join , dann warten Sie, bis alle diese Threads die Thread.Join haben. Das wird ausreichen, um Barrieren zu bilden, damit Sie sicher sind . Dafür habe ich im Moment keine Unterlagen, wohlgemerkt …

EDIT: Ihr Beispielcode ist sicher. Zu keinem Zeitpunkt greifen zwei Threads auf dasselbe Element zu – es ist so, als hätten sie jeweils separate Variablen. Dies ist jedoch für sich allein nicht sinnvoll. Zu einem bestimmten Zeitpunkt möchten die Threads normalerweise den Status teilen – ein Thread möchte lesen, was ein anderer geschrieben hat. Sonst hat es keinen Sinn, in ein Shared-Array statt in eigene private Variablen zu schreiben. Das ist der Punkt, an dem Sie vorsichtig sein müssen – die Koordination zwischen Threads.

MSDN-Dokumentation zu Arrays sagt:

Öffentliche statische Member (Shared in Visual Basic) dieses Typs sind threadsicher. Es ist nicht garantiert, dass alle Instanzmitglieder Thread-sicher sind.

Diese Implementierung bietet keinen synchronisierten (threadsicheren) Wrapper für ein Array. .NET Framework-classn, die auf Array basieren, stellen jedoch ihre eigene synchronisierte Version der Auflistung mithilfe der SyncRoot-Eigenschaft bereit.

Das Aufzählen durch eine Sammlung ist an sich kein Thread-sicheres Verfahren. Auch wenn eine Auflistung synchronisiert wird, können andere Threads die Auflistung weiterhin ändern, wodurch der Enumerator eine Ausnahme austriggers. Um die Threadsicherheit während der Enumeration zu gewährleisten, können Sie entweder die Auflistung während der gesamten Enumeration sperren oder die Ausnahmen abfangen, die sich aus Änderungen anderer Threads ergeben.

Also nein, sie sind nicht threadsicher.

Wenn eine Sammlung “nicht threadsicher” ist, bedeutet dies, dass gleichzeitige Zugriffe intern fehlschlagen können (zB das erste Element von List kann nicht gelesen werden, während ein anderer Thread ein Element am Ende der Liste hinzufügt: die Liste ändert möglicherweise die Größe des zugrunde liegenden Arrays, und der Lesezugriff wird möglicherweise auf das neue Array verlagert, bevor die Daten in das Array kopiert wurden.

Solche Fehler sind bei Arrays nicht möglich, da Arrays eine feste Größe haben und keine solchen Strukturänderungen aufweisen. Ein Array mit drei Elementen ist nicht mehr oder weniger Thread-sicher als drei Variablen.

Die C # -Spezifikation sagt nichts darüber aus; aber es ist klar, wenn Sie IL kennen und lesen Sie die CLI-Spezifikation – Sie könnten eine verwaltete Referenz (wie diejenigen für C # “ref” -Parameter) zu einem Element in einem Array erhalten und dann sowohl normale und flüchtige Lasten und speichert es zu tun. Die CLI-Spezifikation beschreibt die Thread-Sicherheitsgarantien für solche Lasten und Speicher (z. B. Atomizität für Elemente < = 32 Bit)

Wenn ich also Ihre Frage richtig verstehe, wollen Sie ein Array mit verschiedenen Threads füllen, aber jedem Array-Element nur einmal zuweisen? Wenn ja, ist das absolut threadsicher.

Das Beispiel, das Sie bereitstellen, ähnelt sehr der Art und Weise, auf die Microsoft eigene parallele Erweiterungen zu C # 4.0 arbeiten.

Diese für Schleife:

 for (int i = 0; i < 100; i++) { a[i] = a[i]*a[i]; } 

wird

 Parallel.For(0, 100, delegate(int i) { a[i] = a[i]*a[i]; }); 

Also, ja, dein Beispiel sollte in Ordnung sein. Hier ist ein älterer Blogbeitrag über die neue parallele Unterstützung in C #.