51 votes

Les tableaux C # sont-ils sécurisés?

En particulier

  1. Créez une fonction pour prendre un tableau et un index en tant que paramètres.
  2. Créez un tableau d'éléments.
  3. Créez une boucle de comptage.
  4. À l'intérieur de la boucle sur un nouveau thread, attribuez une nouvelle instance de l'objet au tableau à l'aide de l'indexeur transmis.

Je sais comment gérer les threads, etc. Ce qui m'intéresse, c'est 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(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);
    }
}
 

Merci

Gary

44voto

Jon Skeet Points 692016

Je crois que si chaque thread ne fonctionne que sur une autre partie du tableau, tout ira bien. Si vous allez partager des données (j'. e. communiquer entre les threads), alors vous aurez besoin d'une sorte de barrière de mémoire pour éviter de modèle de mémoire de questions.

Je crois que si vous frayer un tas de fils, dont chacun remplit sa propre section de la matrice, puis attendre pour tous ces threads pour finir à l'aide d' Thread.Join, que cela va en faire assez en termes de barrières pour vous d'être en sécurité. Je n'ai pas de documents à l'appui pour l'instant, vous l'esprit ...

EDIT: Votre exemple de code est sûr. À aucun moment les deux threads accèdent à la même élément - c'est comme si ils ont chacun des variables distinctes. Cependant, qui n'a pas tendance à être utile sur son propre. À un certain point, normalement, les threads ne voulez partager un thread aurez envie de lire ce que l'autre a écrit. Sinon, il n'y a aucun point en eux de l'écriture dans un tableau partagé au lieu de dans leurs propres variables privées. C'est le point sur lequel vous devez être prudent - la coordination entre les threads.

25voto

Joren Points 7911

La documentation MSDN sur les Tableaux , dit:

Public static (Partagé en Visual Basic) les membres de ce type sont thread-safe. Tous les membres de l'instance ne sont pas garanti pour être thread-safe.

Cette mise en oeuvre ne pas fournir une synchronisée (thread-safe) de l'enveloppe pour un Tableau; cependant, .NET Framework classes sur la base de la Matrice de fournir à leurs propre version synchronisée de la de la collecte à l'aide de la SyncRoot de la propriété.

L'énumération d'une collection est pas intrinsèquement un thread-safe procédure. Même lorsqu'une collection est synchronisée, les autres threads peuvent toujours modifier la collection, ce qui provoque l'agent recenseur pour lever une exception. Pour garantir la sécurité des threads au cours de l'énumération, vous pouvez verrouiller la collection pendant toute la l'énumération ou intercepter les exceptions résultant des modifications apportées par d'autres les threads.

Donc non, ils ne sont pas thread-safe.

14voto

Daniel Points 7960

Généralement quand une collection est dit "non thread-safe" qui signifie que les accès simultanés peuvent échouer à l'interne (par exemple, pas sûre de lire le premier élément de la Liste<T>, tandis qu'un autre thread ajoute un élément à la fin de la liste: la Liste<T> peut redimensionner le tableau sous-jacent et de la lecture, l'accès peut aller vers le nouveau tableau avant de les données ont été copiées).

De telles erreurs sont impossibles avec les tableaux car les tableaux sont de taille fixe et n'ont pas une telle structure de "changements". Un tableau de trois éléments n'est pas plus ou moins "thread-safe" de trois variables.

La spécification C# ne dit rien à ce sujet; mais il est clair que si vous savez IL et lire la spécification CLI - vous pu obtenir un gérés de référence (comme ceux utilisés pour le C# "ref" paramètres) d'un élément à l'intérieur d'un tableau, puis faire à la fois normal et de la volatilité des charges et des magasins à elle. Les spécifications CLI décrit le fil des garanties de sécurité pour de telles charges et les magasins (par exemple, l'atomicité pour les éléments <=32 bits)

Donc, si je suis unterstanding votre question correctement, vous voulez remplir un tableau à l'aide des threads différents, mais attribue à chaque élément du tableau qu'une seule fois? Si oui, c'est parfaitement thread-safe.

5voto

Eric Points 4139

L'exemple que vous donnez est très similaire à la façon dont fonctionnent les propres extensions parallèles de C # 4.0 de Microsoft.

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 OK. Voici un article de blog plus ancien sur le nouveau support parallèle en C #.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X