Collections thread-safe
Le .NET Framework 4 introduit l'espace de noms System.Collections.Concurrent, qui inclut plusieurs classes de collections qui sont à la fois thread-safe et évolutives. Plusieurs threads peuvent, sans risque et de façon efficace, ajouter ou supprimer des éléments de ces collections, sans nécessiter une synchronisation supplémentaire dans le code utilisateur. Lorsque vous écrivez du nouveau code, utilisez les classes de collections simultanées chaque fois que la collection écrit simultanément dans plusieurs threads. Si vous ne faites que lire à partir d'une collection partagée, vous pouvez utiliser les classes de l'espace de noms System.Collections.Generic. Nous vous recommandons de ne pas utiliser les classes de collections 1.0 à moins que vous ne deviez cibler le .NET Framework 1.1 ou une version antérieure.
Synchronisation de threads dans les collections .NET Framework 1.0 et 2.0
Les collections introduites dans le .NET Framework 1.0 se trouvent dans l'espace de noms System.Collections. Ces collections, qui incluent les ArrayList et Hashtable souvent utilisés, fournissent une certaine sécurité des threads via la propriété Synchronized, qui retourne un wrapper thread-safe autour de la collection. Le wrapper fonctionne en verrouillant l'ensemble de la collection à chaque opération d'ajout ou de suppression. Par conséquent, chaque thread qui essaie d'accéder à la collection doit attendre son tour pour prendre le verrou. Ce fonctionnement n'est pas évolutif et peut provoquer une importante dégradation des performances pour les grandes collections. De même, la conception n'est pas complètement protégée contre les conditions de concurrence. Pour plus d'informations, consultez Synchronisation des collections génériques (page éventuellement en anglais) sur le site Web MSDN.
Les classes de collections introduites dans le .NET Framework 2.0 se trouvent dans l'espace de noms System.Collections.Generic. Il s'agit notamment de List<T>, Dictionary<TKey, TValue>, etc. Ces classes fournissent une sécurité de type et des performances améliorées par rapport aux classes du .NET Framework 1.0. Toutefois, les classes de collections .NET Framework 2.0 ne fournissent pas de synchronisation des threads. Le code utilisateur doit fournir toute la synchronisation lorsque des éléments sont ajoutés ou supprimés sur plusieurs threads simultanément.
Nous recommandons les classes de collections simultanées du .NET Framework 4 car elles ne fournissent pas uniquement la sécurité de type des classes de collections .NET Framework 2.0, mais également plus d'efficacité et de sécurité des threads que les collections .NET Framework 1.0.
Verrouillage de granularité fine et mécanismes sans verrou
Certains types de collections simultanés utilisent des mécanismes de synchronisation légers tels que SpinLock, SpinWait, SemaphoreSlim et CountdownEvent, qui sont des nouveautés du .NET Framework 4. Ces types de synchronisation utilisent en général la rotation intensive pendant de courtes périodes avant de mettre le thread dans un véritable état d'attente. Lorsque les temps d'attente sont supposés être très courts, la rotation est beaucoup moins gourmande en ressources informatiques que l'attente, qui implique une transition de noyau complexe. Pour les classes de collections qui utilisent la rotation, cette efficacité signifie que plusieurs threads peuvent ajouter et supprimer des éléments à un taux très élevé. Pour plus d'informations sur la rotation par rapport au blocage, consultez SpinLock et SpinWait.
Les classes ConcurrentStack<T> et ConcurrentQueue<T> n'utilisent pas de verrous du tout. À la place, ils se reposent sur des opérations Interlocked pour accomplir la sécurité des threads.
Remarque |
---|
Étant donné que les classes de collections simultanées prennent en charge ICollection, elles fournissent des implémentations pour les propriétés IsSynchronized et SyncRoot, bien que ces propriétés ne soient pas pertinentes.IsSynchronized retourne toujours false et SyncRoot a toujours la valeur null (Nothing en Visual Basic). |
Le tableau suivant répertorie les types de collections dans l'espace de noms System.Collections.Concurrent.
Type |
Description |
---|---|
Fournit des fonctionnalités de délimitation et de blocage pour tout type qui implémente IProducerConsumerCollection<T>. Pour plus d'informations, consultez Vue d'ensemble de BlockingCollection. |
|
Implémentation thread-safe d'un dictionnaire de paires clé-valeur. |
|
Implémentation thread-safe d'une file d'attente FIFO (premier entré, premier sorti). |
|
Implémentation thread-safe d'une pile LIFO (dernier entré, premier sorti). |
|
Implémentation thread-safe d'une collection non ordonnée d'éléments. |
|
Interface qu'un type doit implémenter pour être utilisé dans une BlockingCollection. |
Rubriques connexes
Titre |
Description |
---|---|
Décrit les fonctionnalités fournies par le type BlockingCollection<T>. |
|
Comment : ajouter et supprimer des éléments d'un ConcurrentDictionary |
Décrit comment ajouter et supprimer des éléments d'un ConcurrentDictionary<TKey, TValue> |
Comment : ajouter et prendre des éléments individuellement dans un BlockingCollection |
Décrit comment ajouter et extraire des éléments d'une collection bloquante sans utiliser l'énumérateur en lecture seule. |
Comment : ajouter des fonctionnalités de liaison et de blocage à une classe de collection |
Décrit comment utiliser toute classe de collection en tant que mécanisme de stockage sous-jacent pour une collection IProducerConsumerCollection<T>. |
Comment : utiliser la boucle ForEach pour supprimer les éléments d'un BlockingCollection |
Décrit comment utiliser foreach (For Each en Visual Basic) pour supprimer tous les éléments d'une collection bloquante. |
Comment : utiliser des tableaux de collections de blocage dans un pipeline |
Décrit comment utiliser en même temps plusieurs collections bloquantes pour implémenter un pipeline. |
Comment : créer un pool d'objets à l'aide d'un ConcurrentBag |
Indique comment utiliser un conteneur simultané pour améliorer les performances dans les scénarios où vous pouvez réutiliser des objets au lieu d'en créer continuellement de nouveaux. |