Les threads des tableaux C # sont-ils sûrs?

En particulier

  1. Créez une fonction pour prendre un tableau et un index en tant que parameters.
  2. Créez un tableau d’éléments.
  3. Créez une boucle de comptage.
  4. Dans la boucle d’un nouveau thread, assignez une nouvelle instance de l’object au tableau en utilisant l’indexeur transmis.

Je sais comment gérer les threads, etc. Je suis intéressé de savoir si c’est un moyen sûr de faire quelque chose.

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(ssortingng[] 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); } } 

Je crois que si chaque thread ne fonctionne que sur une partie distincte du tableau, tout ira bien. Si vous partagez des données (par exemple, communiquez-les entre les threads), vous aurez besoin d’une sorte de barrière de mémoire pour éviter les problèmes de modèle de mémoire.

Je crois que si vous lancez un tas de threads, chacun Thread.Join sa propre section du tableau, puis attendez que tous ces threads finissent d’utiliser Thread.Join , cela fera assez en termes de barrières pour que vous soyez en sécurité . Je n’ai pas de documentation à ce sujet pour le moment, remarquez …

EDIT: Votre exemple de code est sécurisé. À aucun moment, deux threads n’accèdent au même élément – c’est comme s’ils avaient des variables distinctes. Cependant, cela n’a pas tendance à être utile en soi. À un certain moment, les threads voudront normalement partager leur état – un thread voudra lire ce que l’autre a écrit. Sinon, il est inutile de les écrire dans un tableau partagé plutôt que dans leurs propres variables privées. C’est le point auquel vous devez faire attention – la coordination entre les threads.

La documentation MSDN sur Arrays dit:

Les membres statiques publics (Shared en Visual Basic) de ce type sont thread-safe. Tous les membres d’instance ne sont pas garantis pour être thread-safe.

Cette implémentation ne fournit pas un wrapper synchronisé (thread-safe) pour un tableau; Toutefois, les classes .NET Framework basées sur Array fournissent leur propre version synchronisée de la collection à l’aide de la propriété SyncRoot.

L’énumération via une collection n’est insortingnsèquement pas une procédure de thread-safe. Même lorsqu’une collection est synchronisée, d’autres threads peuvent toujours modifier la collection, ce qui amène l’énumérateur à générer une exception. Pour garantir la sécurité des threads pendant l’énumération, vous pouvez soit verrouiller la collection pendant toute l’énumération, soit intercepter les exceptions résultant des modifications apscopes par d’autres threads.

Donc non, ils ne sont pas thread-safe.

Généralement, lorsqu’une collection est dite «pas threadsafe», cela signifie que les access simultanés peuvent échouer en interne (par exemple, il n’est pas sûr de lire le premier élément de List tandis qu’un autre ajoute un élément à la fin de la liste) peut redimensionner le tableau sous-jacent et l’access en lecture peut aller au nouveau tableau avant que les données y soient copiées).

De telles erreurs sont impossibles avec les baies car les baies sont de taille fixe et ne comportent pas de telles modifications. Un tableau à trois éléments n’est ni plus ni moins sûr que trois variables.

La spécification C # ne dit rien à ce sujet. mais il est clair si vous connaissez IL et lisez la spécification CLI – vous pourriez obtenir une référence gérée (comme celles utilisées pour les parameters C # “ref”) à un élément dans un tableau et y effectuer des charges et des stockages normaux et volatiles. La spécification de l’interface de ligne de commande décrit les garanties de sécurité des threads pour ces charges et ces magasins (par exemple, atomicité pour les éléments <= 32 bits).

Donc, si je ne comprends pas bien votre question, vous voulez remplir un tableau en utilisant différents threads, mais n’atsortingbuez qu’une seule fois à chaque élément du tableau? Si c’est le cas, c’est parfaitement compatible avec les threads.

L’exemple que vous fournissez est très similaire à la manière dont fonctionnent les extensions Parallel de Microsoft vers C # 4.0.

Ceci pour la boucle:

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

devient

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

Donc, oui, votre exemple devrait être correct. Voici un ancien article sur le nouveau support parallèle en C #.