Condividi tramite


Strutture di dati per la programmazione in parallelo

La versione 4 di .NET Framework introduce molti nuovi tipi particolarmente utili per la programmazione in parallelo, fra cui un set di classi di insiemi simultanei, primitive di sincronizzazione leggere e tipi per l'inizializzazione differita. Questi tipi possono essere utilizzati con qualsiasi codice di applicazione multithreading, compresi Task Parallel Library e PLINQ.

Classi di insiemi simultanei

Le classi di insiemi nello spazio dei nomi System.Collections.Concurrent forniscono operazioni di aggiunta e rimozione thread-safe che, laddove possibile, evitano i blocchi. Quando i blocchi sono necessari, tali classi utilizzano blocchi con granularità fine. A differenza degli insiemi introdotti nelle versioni 1.0 e 2.0 di .NET Framework, una classe di insiemi simultanei non richiede l'acquisizione di blocchi da parte del codice utente quando quest'ultimo accede agli elementi. Le classi di insiemi simultanei possono migliorare significativamente le prestazioni dei tipi quali System.Collections.ArrayList e System.Collections.Generic.List<T> (con blocco implementato dall'utente) negli scenari in cui più thread aggiungono e rimuovono elementi da un insieme.

Nella tabella seguente vengono elencate le nuove classi di insiemi simultanei:

Tipo

Descrizione

System.Collections.Concurrent.BlockingCollection<T>

Fornisce funzionalità di blocco e limitazione per gli insiemi thread-safe che implementano System.Collections.Concurrent.IProducerConsumerCollection<T>. I thread producer si bloccano in caso di assenza di slot disponibili o se l'insieme è completo. I thread consumer si bloccano se l'insieme è vuoto. Questo tipo supporta inoltre l'accesso non bloccante da parte di consumer e producer. L'oggetto BlockingCollection<T> può essere utilizzato come una classe base o un archivio di backup per fornire funzionalità di blocco e limitazione per qualsiasi classe di insiemi che supporta IEnumerable<T>.

System.Collections.Concurrent.ConcurrentBag<T>

Implementazione di contenitore thread-safe che fornisce operazioni scalabili di aggiunta e get.

System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>

Tipo di dizionario simultaneo e scalabile.

System.Collections.Concurrent.ConcurrentQueue<T>

Coda FIFO simultanea e scalabile.

System.Collections.Concurrent.ConcurrentStack<T>

Stack LIFO simultaneo e scalabile.

Per ulteriori informazioni, vedere Insiemi thread-safe.

Primitive di sincronizzazione

Le nuove primitive di sincronizzazione nello spazio dei nomi System.Threading evitano i dispendiosi meccanismi di blocco presenti nel codice multithreading legacy e pertanto sono in grado di offrire una concorrenza con granularità fine e una maggiore velocità di esecuzione. Per alcuni dei nuovi tipi, ad esempio System.Threading.Barrier e System.Threading.CountdownEvent, non esiste alcuna controparte nelle prime versioni di .NET Framework.

Nella tabella seguente sono elencati i nuovi tipi di sincronizzazione:

Tipo

Descrizione

System.Threading.Barrier

Consente a più thread di utilizzare un algoritmo in parallelo fornendo un punto in cui ogni attività può segnalare il proprio arrivo e quindi bloccarsi fino all'arrivo di tutte le attività o di una parte di esse. Per ulteriori informazioni, vedere Barriera (.NET Framework).

System.Threading.CountdownEvent

Semplifica gli scenari di fork e join fornendo un facile meccanismo di incontro. Per ulteriori informazioni, vedere CountdownEvent.

System.Threading.ManualResetEventSlim

Primitiva di sincronizzazione simile a System.Threading.ManualResetEvent. L'oggetto ManualResetEventSlim è più leggero ma può essere utilizzato solo per le comunicazioni interne del processo. Per ulteriori informazioni, vedere ManualResetEvent e ManualResetEventSlim.

System.Threading.SemaphoreSlim

Primitiva di sincronizzazione che limita il numero di thread che possono accedere simultaneamente a una risorsa o a un pool di risorse. Per ulteriori informazioni, vedere Semaphore e SemaphoreSlim.

System.Threading.SpinLock

Primitiva di blocco di esclusione reciproca che impone a un thread che sta tentando di acquisire il blocco di restare in attesa in un ciclo (spin) per un periodo di tempo prima di cedere il proprio il quantum. Negli scenari in cui si prevede che l'attesa del blocco sarà breve, SpinLock offre prestazioni migliori rispetto alle altre forme di blocco. Per ulteriori informazioni, vedere SpinLock.

System.Threading.SpinWait

Tipo leggero e di dimensioni ridotte che eseguirà spin per un determinato periodo di tempo e che infine metterà il thread in uno stato di attesa se viene superato il numero di spin. Per ulteriori informazioni, vedere SpinWait.

Per ulteriori informazioni, vedere:

Classi di inizializzazione differita

Nell'inizializzazione differita la memoria per un oggetto viene allocata solo quando occorre. L'inizializzazione differita può migliorare le prestazioni distribuendo uniformemente le allocazioni degli oggetti nel corso della durata di un programma. È possibile consentire l'inizializzazione differita di qualsiasi tipo personalizzato tramite il wrapping del tipo Lazy<T>.

Nella tabella seguente sono elencati i tipi di inizializzazione differita:

Tipo

Descrizione

System.Lazy<T>

Fornisce un'inizializzazione differita leggera e thread-safe.

System.Threading.ThreadLocal<T>

Fornisce per ogni singolo thread un valore con inizializzazione differita, in cui ogni thread richiama in modo differito la funzione di inizializzazione.

System.Threading.LazyInitializer

Fornisce metodi statici che evitano la necessità di allocare un'istanza dedicata con inizializzazione differita. Tali metodi, invece, utilizzano riferimenti per garantire che le destinazioni siano state inizializzate al momento dell'accesso.

Per ulteriori informazioni, vedere Inizializzazione differita.

Eccezioni di aggregazione

È possibile utilizzare il tipo System.AggregateException per acquisire più eccezioni generate contemporaneamente in thread separati e restituirle al thread di unione come singola eccezione. I tipi System.Threading.Tasks.Task e System.Threading.Tasks.Parallel e PLINQ utilizzano ampiamente AggregateException a tale scopo. Per ulteriori informazioni, vedere Procedura: gestire le eccezioni generate dalle attività e Procedura: gestire le eccezioni in una query PLINQ.

Vedere anche

Riferimenti

System.Collections.Concurrent

System.Threading

Concetti

Programmazione parallela in .NET Framework