Condividi tramite


Raccolte thread-safe

Lo spazio dei nomi System.Collections.Concurrent include diverse classi di raccolta che sono sia thread-safe che scalabili. Più thread possono aggiungere o rimuovere in modo sicuro ed efficiente elementi da queste raccolte, senza richiedere una sincronizzazione aggiuntiva nel codice utente. Quando si scrive nuovo codice, usare le classi di raccolta simultanee per scrivere più thread nella raccolta contemporaneamente. Se leggi solo da una raccolta condivisa, è possibile usare le classi nello spazio dei nomi System.Collections.Generic.

System.Collections e System.Collections.Generic

Le classi di collezione nello spazio dei nomi System.Collections comprendono ArrayList e Hashtable. Queste classi forniscono una certa sicurezza dei thread tramite la proprietà Synchronized, che restituisce un wrapper thread-safe per la raccolta. Il wrapper funziona bloccando l'intera raccolta in ogni operazione di aggiunta o rimozione. Di conseguenza, ogni thread che tenta di accedere alla raccolta deve attendere per il suo turno di prendere l'unico blocco. Questo processo non è scalabile e può causare un calo significativo delle prestazioni per le raccolte di grandi dimensioni. Inoltre, il design non è protetto da condizioni di corsa. Per altre informazioni, vedere Sincronizzazione nelle raccolte generiche.

Le classi di collezione nello spazio dei nomi System.Collections.Generic comprendono List<T> e Dictionary<TKey,TValue>. Queste classi offrono prestazioni e sicurezza dei tipi migliorate rispetto alle System.Collections classi. Tuttavia, le System.Collections.Generic classi non forniscono alcuna sincronizzazione dei thread. Il codice utente deve fornire tutta la sincronizzazione quando gli elementi vengono aggiunti o rimossi in più thread contemporaneamente.

È consigliabile usare le classi di raccolte simultanee nello spazio dei System.Collections.Concurrent nomi perché offrono sicurezza dei tipi e una sicurezza dei thread più efficiente e completa.

Meccanismi di blocco e senza blocco con granularità fine

Alcuni tipi di raccolta simultanei usano meccanismi di sincronizzazione leggeri, ad esempio SpinLock, SpinWait, SemaphoreSlim, e CountdownEvent. Questi tipi di sincronizzazione usano in genere la rotazione occupata per brevi periodi prima di inserire il thread in uno stato vero Wait. Quando si prevede che i tempi di attesa siano brevi, la rotazione è molto meno costosa dal punto di vista computazionale rispetto all'attesa, che comporta una transizione del kernel costosa. Per le classi di raccolta che usano la rotazione, questa efficienza significa che più thread possono aggiungere e rimuovere elementi a una velocità elevata. Per altre informazioni sulla rotazione e sul blocco, vedere SpinLock e SpinWait.

Le classi ConcurrentQueue<T> e ConcurrentStack<T> non usano blocchi. Invece, si basano sulle Interlocked operazioni per ottenere la sicurezza dei thread.

Annotazioni

Poiché le classi di raccolte simultanee supportano ICollection, forniscono implementazioni per le IsSynchronized proprietà e SyncRoot , anche se queste proprietà sono irrilevanti. IsSynchronized restituisce false sempre e, SyncRoot è sempre null (Nothing in Visual Basic).

Nella tabella seguente sono elencati i tipi di raccolta nello spazio dei System.Collections.Concurrent nomi:

TIPO Descrizione
BlockingCollection<T> Fornisce funzionalità di delimitazione e blocco per qualsiasi tipo che implementa IProducerConsumerCollection<T>. Per altre informazioni, vedere Cenni preliminari su BlockingCollection.
ConcurrentDictionary<TKey,TValue> Implementazione thread-safe di un dizionario di coppie chiave-valore.
ConcurrentQueue<T> Implementazione thread-safe di una coda FIFO (first-in, first-out).
ConcurrentStack<T> Implementazione thread-safe di uno stack LIFO (ultimo a entrare, primo a uscire).
ConcurrentBag<T> Implementazione sicura per i thread di una raccolta non ordinata di elementi.
IProducerConsumerCollection<T> Interfaccia che un tipo deve implementare per essere utilizzata in un oggetto BlockingCollection.
Titolo Descrizione
Panoramica di BlockingCollection Descrive le funzionalità fornite dal BlockingCollection<T> tipo .
Procedura: Aggiungere e rimuovere elementi da un oggetto ConcurrentDictionary Viene descritto come aggiungere e rimuovere elementi da un oggetto ConcurrentDictionary<TKey,TValue>
Procedura: Aggiungere e acquisire elementi singolarmente da un oggetto BlockingCollection Viene descritto come aggiungere e recuperare elementi da una raccolta di blocco senza utilizzare l'enumeratore di sola lettura.
Procedura: Aggiungere funzionalità di delimitazione e blocco a una raccolta Viene descritto come usare qualsiasi classe di raccolta come meccanismo di archiviazione sottostante per una IProducerConsumerCollection<T> raccolta.
Procedura: Usare ForEach per rimuovere elementi in un oggetto BlockingCollection Viene descritto come utilizzare foreach (For Each in Visual Basic) per rimuovere tutti gli elementi in una raccolta di blocco.
Procedura: Usare matrici di raccolte di blocco in una pipeline Viene descritto come usare più raccolte di blocco contemporaneamente per implementare una pipeline.
Procedura: Creare un pool di oggetti usando un oggetto ConcurrentBag Illustra come usare un contenitore simultaneo per migliorare le prestazioni negli scenari in cui è possibile riutilizzare gli oggetti anziché crearne continuamente di nuovi.

Riferimenti