Structures de données pour la programmation parallèle
Le .NET Framework version 4 contient plusieurs nouveaux types utiles pour la programmation parallèle, notamment un ensemble de classes de collection simultanée, des primitives de synchronisation légères et des types pour l'initialisation tardive. Vous pouvez utiliser ces types avec tout code d'application multithread, notamment avec la bibliothèque parallèle de tâches et PLINQ.
Classes de collection simultanée
Les classes de collection de l'espace de noms System.Collections.Concurrent permettent des opérations d'ajout et de suppression thread-safe qui évitent les verrous lorsque cela est possible et utilisent un verrouillage affiné lorsque l'utilisation de verrous est nécessaire. Contrairement aux collections présentées dans le .NET Framework version 1.0 et 2.0, une classe de collection simultanée ne nécessite pas que le code utilisateur acquière des verrous lorsqu'il accède à des éléments. Les classes de collection simultanée peuvent améliorer considérablement les performances des types tels que System.Collections.ArrayList et System.Collections.Generic.List<T> (avec verrouillage implémenté par utilisateur) dans les scénarios où plusieurs threads ajoutent et suppriment des éléments d'une collection.
Le tableau suivant répertorie les nouvelles classes de collection simultanée :
Type |
Description |
---|---|
Fournit des fonctions bloquantes et englobantes pour les collections thread-safe qui implémentent System.Collections.Concurrent.IProducerConsumerCollection<T>. Les threads producteurs se bloquent si aucun emplacement n'est disponible ou si la collection est complète. Les threads consommateurs se bloquent si la collection est vide. Ce type prend également en charge l'accès non bloquant par les consommateurs et les producteurs. BlockingCollection<T> peut être utilisé comme classe de base ou magasin de stockage pour le blocage et la délimitation des classes de collection prenant en charge IEnumerable<T>. |
|
Une implémentation de sac thread-safe qui permet des opérations évolutives d'ajout et d'extraction. |
|
System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue> |
Type de dictionnaire simultané et évolutif. |
File d'attente FIFO simultanée et évolutive. |
|
Pile LIFO simultanée et évolutive. |
Pour plus d'informations, consultez Collections thread-safe.
Primitives de synchronisation
Les nouvelles primitives de synchronisation dans l'espace de noms System.Threading permettent l'accès concurrentiel à grains fins et de meilleures performances en évitant les mécanismes de verrouillage coûteux trouvés dans le code multithread hérité. Certains nouveaux types, tels que System.Threading.Barrier et System.Threading.CountdownEvent n'ont pas d'équivalents dans les premières version du .NET Framework.
Le tableau suivant répertorie les nouveaux types de synchronisation :
Type |
Description |
---|---|
Permet à plusieurs threads de travailler en parallèle sur un algorithme en fournissant un point auquel chaque tâche peut signaler son arrivée puis se bloquer jusqu'à ce que certaines ou toutes les tâches soient arrivées. Pour plus d'informations, consultez Cloisonnement (.NET Framework). |
|
Simplifie les scénarios de bifurcation/jointure en fournissant un mécanisme de rendez-vous facile. Pour plus d'informations, consultez CountdownEvent. |
|
Synchronisation de base semblable à System.Threading.ManualResetEvent. ManualResetEventSlim est léger mais peut être utilisé uniquement pour la communication intra-processus. Pour plus d'informations, consultez ManualResetEvent et ManualResetEventSlim. |
|
Primitive de synchronisation qui limite le nombre de threads qui peuvent accéder simultanément à une ressource ou un pool de ressources. Pour plus d'informations, consultez Semaphore et SemaphoreSlim. |
|
Primitive de verrou d'exclusion mutuelle qui fait attendre dans une boucle (ou tourner) le thread qui essaie d'acquérir le verrou pendant une certaine durée avant de transmettre son quantum. Dans les scénarios où l'attente du verrou est censée être courte, SpinLock offre de meilleures performances que les autres types de verrouillage. Pour plus d'informations, consultez SpinLock. |
|
Type petit et léger qui tournera pendant une durée spécifiée et mettra finalement le thread en état d'attente si le nombre de tours est dépassé. Pour plus d'informations, consultez SpinWait. |
Pour plus d'informations, consultez :
Comment : utiliser le verrouillage spinlock pour une synchronisation de bas niveau
Comment : synchroniser des opérations simultanées avec un objet Barrier.
Classes d'initialisation tardive
Avec l'initialisation tardive, la mémoire d'un objet n'est pas allouée tant que cela n'est pas nécessaire. L'initialisation tardive peut améliorer les performances en répartissant de façon égale les allocations d'objets pendant la durée de vie d'un programme. Vous pouvez activer l'initialisation tardive pour tout type personnalisé en incluant dans un wrapper le type Lazy<T>.
Le tableau suivant répertorie les types d'initialisation tardive :
Type |
Description |
---|---|
Fournit une initialisation tardive légère et thread-safe. |
|
Fournit une valeur initialisée de façon tardive par thread, avec chaque thread appelant de façon tardive la fonction d'initialisation. |
|
Fournit des méthodes statiques qui évitent le besoin d'allouer une instance d'initialisation tardive dédiée. À la place, elles utilisent des références pour vérifier que les cibles ont été initialisées. |
Pour plus d'informations, consultez Initialisation tardive.
Agrégat d'exceptions
Le type System.AggregateException peut être utilisé pour capturer plusieurs exceptions levées simultanément sur des threads séparés et les retourner au thread joint comme une exception unique. Les types System.Threading.Tasks.Task et System.Threading.Tasks.Parallel et PLINQ utilisent largement AggregateException à cette fin. Pour plus d'informations, consultez Comment : gérer les exceptions levées par des tâches et Comment : gérer des exceptions dans une requête PLINQ.