Collections thread-safe
.NET Framework 4 introduit l’espace de noms System.Collections.Concurrent, qui contient plusieurs classes de collection qui sont à la fois thread-safe et scalables. Plusieurs threads peuvent, sans risque et de façon efficace, ajouter ou supprimer des éléments dans ces collections, sans nécessiter une synchronisation supplémentaire dans le code utilisateur. Quand vous écrivez du code, utilisez des classes de collections simultanées si plusieurs threads écrivent en même temps dans la collection. Si vous lisez seulement dans 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 runtime .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 fréquemment utilisés, garantissent une certaine cohérence des threads par le biais de 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 tente 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 la concurrence critique. Pour plus d’informations, consultez Synchronisation dans les collections génériques.
Les classes de collection introduites dans le .NET Framework 2.0 se trouvent dans l’espace de noms System.Collections.Generic. Elles comprennent notamment List<T>, Dictionary<TKey,TValue>, etc. Ces classes garantissent une cohérence des types 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 quand des éléments sont ajoutés ou supprimés simultanément sur plusieurs threads.
Nous vous recommandons les classes de collections simultanées de .NET Framework 4, car elles offrent non seulement la cohérence des types des classes de collections .NET Framework 2.0, mais également une cohérence de thread plus efficace et plus complète que les collections .NET Framework 1.0.
Verrouillage de granularité fine et mécanismes sans verrou
Certains types de collections simultanées utilisent des mécanismes de synchronisation légers, comme SpinLock, SpinWait, SemaphoreSlim et CountdownEvent, qui sont nouveaux dans .NET Framework 4. Ces types de synchronisation utilisent généralement 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 coûteuse. 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 et le blocage, consultez SpinLock et SpinWait.
Les classes ConcurrentQueue<T> et ConcurrentStack<T> n’utilisent pas de verrous du tout. Au lieu de cela, elles s’appuient sur des opérations Interlocked pour assurer la cohérence des threads.
Notes
É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
dans Visual Basic).
Le tableau suivant répertorie les types de collections dans l’espace de noms System.Collections.Concurrent.
Type | Description |
---|---|
BlockingCollection<T> | Fournit des fonctionnalités de délimitation et de blocage pour tous les types qui implémentent IProducerConsumerCollection<T>. Pour plus d’informations, consultez Vue d’ensemble de BlockingCollection. |
ConcurrentDictionary<TKey,TValue> | Implémentation thread-safe d’un dictionnaire de paires clé-valeur. |
ConcurrentQueue<T> | Implémentation thread-safe d’une file d’attente FIFO (premier entré, premier sorti). |
ConcurrentStack<T> | Implémentation thread-safe d’une pile LIFO (dernier entré, premier sorti). |
ConcurrentBag<T> | Implémentation thread-safe d’une collection non ordonnée d’éléments. |
IProducerConsumerCollection<T> | Interface qu’un type doit implémenter pour être utilisé dans un BlockingCollection . |
Rubriques connexes
Titre | Description |
---|---|
Vue d'ensemble de BlockingCollection | Décrit la fonctionnalité fournie par le type BlockingCollection<T>. |
Guide pratique pour ajouter et supprimer des éléments d'un ConcurrentDictionary | Décrit comment ajouter et supprimer des éléments dans un ConcurrentDictionary<TKey,TValue>. |
Procédure : ajouter et prendre des éléments individuellement dans un BlockingCollection | Décrit comment ajouter et récupérer des éléments dans une collection de blocage sans utiliser l’énumérateur en lecture seule. |
Procédure : ajouter des fonctionnalités de délimitation et de blocage à une collection | Décrit comment utiliser une classe de collection comme mécanisme de stockage sous-jacent pour une collection IProducerConsumerCollection<T>. |
Procédure : utiliser la boucle ForEach pour supprimer les éléments d’un BlockingCollection | Décrit comment utiliser foreach , (For Each dans Visual Basic) pour supprimer tous les éléments d’une collection de blocage. |
Procédure : utiliser des tableaux de collections de blocage dans un pipeline | Décrit comment utiliser simultanément plusieurs collections de blocage pour implémenter un pipeline. |
Procédure : créer un pool d’objets à l’aide d’un ConcurrentBag | Montre 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. |