105 votes

Sécurité des threads List.Add()

Je comprends que, en général, une liste n’est pas thread-safe, mais y a-t-il quelque chose de mal à simplement ajouter des éléments dans une liste si les threads jamais exécuter toutes autres opérations sur la liste (par exemple il traversant) ?

Exemple :

79voto

Talljoe Points 8423

Les coulisses de beaucoup de choses, y compris la réaffectation de tampons et de copier des éléments. Ce code sera en danger. Très simplement, il n'y a pas d'opérations atomiques lors de l'ajout à une liste, à tout le moins de la "Longueur" de la propriété a besoin d'être mises à jour, et l'élément doit être mis au bon endroit, et (s'il y a une variable séparée) l'index doit être mis à jour. Plusieurs threads peuvent empiéter les uns sur les autres. Et si la croissance est nécessaire, alors il ya beaucoup plus de choses. Si quelque chose est écrit une liste de rien d'autre en lecture ou en écriture à elle.

Dans .NET 4.0, nous avons simultanées dans les collections, qui sont haut la main des threads et ne nécessitent pas de serrures.

14voto

BrokenGlass Points 91618

Vous approche actuelle n’est pas thread-safe - je dirais éviter au total - puisque vous faites essentiellement une transformation de données PLINQ peut être une meilleure approche (je sais il s’agit d’un exemple simplifié, mais en fin de compte vous projeter chaque transaction dans un autre objet « état »).

6voto

Jon Hanna Points 40291

Il n'est pas déraisonnable de demander. Il y sont des cas où les méthodes qui peuvent causer des thread-les questions de sécurité en combinaison avec d'autres méthodes sont sans danger si elles sont la seule méthode appelée.

Cependant, ce n'est pas un cas, quand vous considérez le code indiqué dans le réflecteur:

public void Add(T item)
{
    if (this._size == this._items.Length)
    {
        this.EnsureCapacity(this._size + 1);
    }
    this._items[this._size++] = item;
    this._version++;
}

Même si EnsureCapacity était en elle-même thread-safe (et ce n'est surtout pas), le code ci-dessus est clairement ne va pas être thread-safe, compte tenu de la possibilité d'appels simultanés à l'opérateur d'incrémentation causant mal écrit.

Soit de verrouillage, utilisez ConcurrentList, ou peut-être utiliser un verrou sans file d'attente comme le lieu de plusieurs threads écrire et le lire à partir d' - soit directement ou par le remplissage d'une liste, avec elle, après qu'ils ont fait leur travail (je suis en supposant que les multiples et simultanées écrit suivi par un seul thread de lecture est à votre patron ici, à en juger d'après votre question, parce que sinon, je ne vois pas comment l'état où Add est la seule méthode appelée pourrait être d'une quelconque utilité).

5voto

Linkgoron Points 3060

Cela entraînerait des problèmes car la liste est construite sur un tableau et n’est pas thread-safe, que vous pourriez obtenir index hors exception de limites ou certaines valeurs, la substitution d’autres valeurs, en fonction d’où sont les fils. Fondamentalement, ne le faites pas.

Il y a plusieurs problème potentiel... Juste ne pas. Si vous avez besoin d’une collection de safe thread, soit utiliser un verrou ou une des collections System.Collections.Concurrent.

3voto

Bas Smit Points 205
<blockquote> <p>Y a-t-il quelque chose de mal à simplement ajouter des éléments dans une liste si les threads jamais exécuter toutes autres opérations sur la liste ?</p> <p>Réponse courte : Oui.</p><p>Réponse longue : exécutez le programme ci-dessous.</p><pre><code></code></pre></blockquote>

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